Skip to content

Commit a7f459f

Browse files
committed
Improved nested exposures performance, nested exposures doubling fixed
ruby-grape#57 ruby-grape#59
1 parent b8c4fe4 commit a7f459f

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Next Release
22
============
33

44
* Your contribution here.
5+
* [#60] (https://github.com/intridea/grape-entity/issues/59): Performance issues introduced by nested exposures - [@AlexYankee](https://github.com/AlexYankee).
6+
* [#60] (https://github.com/intridea/grape-entity/issues/57): Nested exposure double-exposes a field - [@AlexYankee](https://github.com/AlexYankee).
57

68
0.4.1 (2014-02-13)
79
==================

lib/grape_entity/entity.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,13 @@ def self.expose(*args, &block)
136136
options[:proc] = block if block_given? && block.parameters.any?
137137

138138
@nested_attributes ||= []
139+
139140
args.each do |attribute|
140141
unless @nested_attributes.empty?
141142
attribute = "#{@nested_attributes.last}__#{attribute}"
143+
options[:nested] = true
144+
nested_exposures[@nested_attributes.last.to_sym] ||= {}
145+
nested_exposures[@nested_attributes.last.to_sym][attribute.to_sym] = options
142146
end
143147

144148
exposures[attribute.to_sym] = options
@@ -180,6 +184,16 @@ def self.exposures
180184
@exposures
181185
end
182186

187+
def self.nested_exposures
188+
@nested_exposures ||= {}
189+
190+
if superclass.respond_to? :nested_exposures
191+
@nested_exposures = superclass.nested_exposures.merge(@nested_exposures)
192+
end
193+
194+
@nested_exposures
195+
end
196+
183197
# Returns a hash, the keys are symbolized references to fields in the entity,
184198
# the values are document keys in the entity's documentation key. When calling
185199
# #docmentation, any exposure without a documentation key will be ignored.
@@ -324,7 +338,7 @@ def exposures
324338
end
325339

326340
def valid_exposures
327-
exposures.select do |attribute, exposure_options|
341+
exposures.reject { |a, options| options[:nested] }.select do |attribute, exposure_options|
328342
valid_exposure?(attribute, exposure_options)
329343
end
330344
end
@@ -390,7 +404,7 @@ def self.key_for(attribute)
390404
end
391405

392406
def self.nested_exposures_for(attribute)
393-
exposures.select { |a, _| a.to_s =~ /^#{attribute}__/ }
407+
nested_exposures[attribute] || {}
394408
end
395409

396410
def value_for(attribute, options = {})

spec/grape_entity/entity_spec.rb

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ class BogusEntity < Grape::Entity
9292

9393
subject.exposures.should == {
9494
awesome: {},
95-
awesome__nested: {},
96-
awesome__nested__moar_nested: { as: 'weee' },
97-
awesome__another_nested: { using: 'Awesome' }
95+
awesome__nested: { nested: true },
96+
awesome__nested__moar_nested: { as: 'weee', nested: true },
97+
awesome__another_nested: { using: 'Awesome', nested: true }
9898
}
9999
end
100100

@@ -110,6 +110,26 @@ class BogusEntity < Grape::Entity
110110
}
111111
end
112112

113+
it 'does not represent attributes, declared inside nested exposure, outside of it' do
114+
subject.expose :awesome do
115+
subject.expose(:nested) { |_| "value" }
116+
subject.expose(:another_nested) { |_| "value" }
117+
subject.expose :second_level_nested do
118+
subject.expose(:deeply_exposed_attr) { |_| "value" }
119+
end
120+
end
121+
122+
subject.represent({}).serializable_hash.should == {
123+
awesome: {
124+
nested: "value",
125+
another_nested: "value",
126+
second_level_nested: {
127+
deeply_exposed_attr: "value"
128+
}
129+
}
130+
}
131+
end
132+
113133
it 'is safe if its nested exposures are safe' do
114134
subject.with_options safe: true do
115135
subject.expose :awesome do
@@ -121,6 +141,7 @@ class BogusEntity < Grape::Entity
121141
end
122142

123143
valid_keys = subject.represent({}).valid_exposures.keys
144+
124145
valid_keys.include?(:awesome).should == true && \
125146
valid_keys.include?(:not_awesome).should == false
126147
end

0 commit comments

Comments
 (0)