Skip to content

Commit 5d167cd

Browse files
author
James McCarthy
committed
Allow as: option to accept a proc.
1 parent 1e6aaec commit 5d167cd

File tree

7 files changed

+32
-23
lines changed

7 files changed

+32
-23
lines changed

lib/grape_entity/exposure/base.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ def self.new(attribute, options, conditions, *args, &block)
1111
def initialize(attribute, options, conditions)
1212
@attribute = attribute.try(:to_sym)
1313
@options = options
14-
@key = (options[:as] || attribute).try(:to_sym)
14+
key = options[:as] || attribute
15+
@key = key.respond_to?(:to_sym) ? key.to_sym : key
1516
@is_safe = options[:safe]
1617
@for_merge = options[:merge]
1718
@attr_path_proc = options[:attr_path]
@@ -41,7 +42,7 @@ def nesting?
4142
end
4243

4344
# if we have any nesting exposures with the same name.
44-
def deep_complex_nesting?
45+
def deep_complex_nesting?(entity)
4546
false
4647
end
4748

@@ -102,6 +103,10 @@ def attr_path(entity, options)
102103
end
103104
end
104105

106+
def key(entity=nil)
107+
@key.respond_to?(:call) ? @key.call(entity).try(:to_sym) : @key
108+
end
109+
105110
def with_attr_path(entity, options)
106111
path_part = attr_path(entity, options)
107112
options.with_attr_path(path_part) do

lib/grape_entity/exposure/nesting_exposure.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def valid?(entity)
3030

3131
def value(entity, options)
3232
new_options = nesting_options_for(options)
33-
output = OutputBuilder.new
33+
output = OutputBuilder.new(entity)
3434

3535
normalized_exposures(entity, new_options).each_with_object(output) do |exposure, out|
3636
exposure.with_attr_path(entity, new_options) do
@@ -44,7 +44,7 @@ def valid_value_for(key, entity, options)
4444
new_options = nesting_options_for(options)
4545

4646
result = nil
47-
normalized_exposures(entity, new_options).select { |e| e.key == key }.each do |exposure|
47+
normalized_exposures(entity, new_options).select { |e| e.key(entity) == key }.each do |exposure|
4848
exposure.with_attr_path(entity, new_options) do
4949
result = exposure.valid_value(entity, new_options)
5050
end
@@ -54,7 +54,7 @@ def valid_value_for(key, entity, options)
5454

5555
def serializable_value(entity, options)
5656
new_options = nesting_options_for(options)
57-
output = OutputBuilder.new
57+
output = OutputBuilder.new(entity)
5858

5959
normalized_exposures(entity, new_options).each_with_object(output) do |exposure, out|
6060
exposure.with_attr_path(entity, new_options) do
@@ -65,9 +65,9 @@ def serializable_value(entity, options)
6565
end
6666

6767
# if we have any nesting exposures with the same name.
68-
# delegate :deep_complex_nesting?, to: :nested_exposures
69-
def deep_complex_nesting?
70-
nested_exposures.deep_complex_nesting?
68+
# delegate :deep_complex_nesting?(entity), to: :nested_exposures
69+
def deep_complex_nesting?(entity)
70+
nested_exposures.deep_complex_nesting?(entity)
7171
end
7272

7373
private
@@ -90,15 +90,15 @@ def easy_normalized_exposures(entity, options)
9090

9191
# This method 'merges' subsequent nesting exposures with the same name if it's needed
9292
def normalized_exposures(entity, options)
93-
return easy_normalized_exposures(entity, options) unless deep_complex_nesting? # optimization
93+
return easy_normalized_exposures(entity, options) unless deep_complex_nesting?(entity) # optimization
9494

9595
table = nested_exposures.each_with_object({}) do |exposure, output|
9696
should_expose = exposure.with_attr_path(entity, options) do
9797
exposure.should_expose?(entity, options)
9898
end
9999
next unless should_expose
100-
output[exposure.key] ||= []
101-
output[exposure.key] << exposure
100+
output[exposure.key(entity)] ||= []
101+
output[exposure.key(entity)] << exposure
102102
end
103103
table.map do |key, exposures|
104104
last_exposure = exposures.last
@@ -111,7 +111,7 @@ def normalized_exposures(entity, options)
111111
end
112112
new_nested_exposures = nesting_tail.flat_map(&:nested_exposures)
113113
NestingExposure.new(key, {}, [], new_nested_exposures).tap do |new_exposure|
114-
new_exposure.instance_variable_set(:@deep_complex_nesting, true) if nesting_tail.any?(&:deep_complex_nesting?)
114+
new_exposure.instance_variable_set(:@deep_complex_nesting, true) if nesting_tail.any? { |exposure| exposure.deep_complex_nesting?(entity) }
115115
end
116116
else
117117
last_exposure

lib/grape_entity/exposure/nesting_exposure/nested_exposures.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ def #{name}(*args, &block)
5151
end
5252

5353
# Determine if we have any nesting exposures with the same name.
54-
def deep_complex_nesting?
54+
def deep_complex_nesting?(entity)
5555
if @deep_complex_nesting.nil?
5656
all_nesting = select(&:nesting?)
57-
@deep_complex_nesting = all_nesting.group_by(&:key).any? { |_key, exposures| exposures.length > 1 }
57+
@deep_complex_nesting =
58+
all_nesting
59+
.group_by { |exposure| exposure.key(entity) }
60+
.any? { |_key, exposures| exposures.length > 1 }
5861
else
5962
@deep_complex_nesting
6063
end

lib/grape_entity/exposure/nesting_exposure/output_builder.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ class Entity
33
module Exposure
44
class NestingExposure
55
class OutputBuilder < SimpleDelegator
6-
def initialize
6+
def initialize(entity)
7+
@entity = entity
78
@output_hash = {}
89
@output_collection = []
910
end
@@ -18,7 +19,7 @@ def add(exposure, result)
1819
return unless result
1920
@output_hash.merge! result, &merge_strategy(exposure.for_merge)
2021
else
21-
@output_hash[exposure.key] = result
22+
@output_hash[exposure.key(@entity)] = result
2223
end
2324
end
2425

lib/grape_entity/exposure/represent_exposure.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def ==(other)
2121
end
2222

2323
def value(entity, options)
24-
new_options = options.for_nesting(key)
24+
new_options = options.for_nesting(key(entity))
2525
using_class.represent(@subexposure.value(entity, options), new_options)
2626
end
2727

spec/grape_entity/entity_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class BogusEntity < Grape::Entity
131131
expect(another_nested).to_not be_nil
132132
expect(another_nested.using_class_name).to eq('Awesome')
133133
expect(moar_nested).to_not be_nil
134-
expect(moar_nested.key).to eq(:weee)
134+
expect(moar_nested.key(subject)).to eq(:weee)
135135
end
136136

137137
it 'represents the exposure as a hash of its nested.root_exposures' do
@@ -496,7 +496,7 @@ class Parent < Person
496496
end
497497

498498
exposure = subject.find_exposure(:awesome_thing)
499-
expect(exposure.key).to eq :extra_smooth
499+
expect(exposure.key(subject)).to eq :extra_smooth
500500
end
501501

502502
it 'merges nested :if option' do

spec/grape_entity/exposure/nesting_exposure/nested_exposures_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
44
subject(:nested_exposures) { described_class.new([]) }
55

6-
describe '#deep_complex_nesting?' do
6+
describe '#deep_complex_nesting?(entity)' do
77
it 'is reset when additional exposure is added' do
88
subject << Grape::Entity::Exposure.new(:x, {})
99
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
10-
subject.deep_complex_nesting?
10+
subject.deep_complex_nesting?(subject)
1111
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
1212
subject << Grape::Entity::Exposure.new(:y, {})
1313
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -16,7 +16,7 @@
1616
it 'is reset when exposure is deleted' do
1717
subject << Grape::Entity::Exposure.new(:x, {})
1818
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
19-
subject.deep_complex_nesting?
19+
subject.deep_complex_nesting?(subject)
2020
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
2121
subject.delete_by(:x)
2222
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -25,7 +25,7 @@
2525
it 'is reset when exposures are cleared' do
2626
subject << Grape::Entity::Exposure.new(:x, {})
2727
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
28-
subject.deep_complex_nesting?
28+
subject.deep_complex_nesting?(subject)
2929
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
3030
subject.clear
3131
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil

0 commit comments

Comments
 (0)