Skip to content

Commit 958e23c

Browse files
author
James McCarthy
committed
Allow as: option to accept a proc.
1 parent 0930f60 commit 958e23c

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
@@ -13,7 +13,8 @@ def self.new(attribute, options, conditions, *args, &block)
1313
def initialize(attribute, options, conditions)
1414
@attribute = attribute.try(:to_sym)
1515
@options = options
16-
@key = (options[:as] || attribute).try(:to_sym)
16+
key = options[:as] || attribute
17+
@key = key.respond_to?(:to_sym) ? key.to_sym : key
1718
@is_safe = options[:safe]
1819
@for_merge = options[:merge]
1920
@attr_path_proc = options[:attr_path]
@@ -43,7 +44,7 @@ def nesting?
4344
end
4445

4546
# if we have any nesting exposures with the same name.
46-
def deep_complex_nesting?
47+
def deep_complex_nesting?(entity)
4748
false
4849
end
4950

@@ -104,6 +105,10 @@ def attr_path(entity, options)
104105
end
105106
end
106107

108+
def key(entity=nil)
109+
@key.respond_to?(:call) ? @key.call(entity).try(:to_sym) : @key
110+
end
111+
107112
def with_attr_path(entity, options)
108113
path_part = attr_path(entity, options)
109114
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
@@ -32,7 +32,7 @@ def valid?(entity)
3232

3333
def value(entity, options)
3434
new_options = nesting_options_for(options)
35-
output = OutputBuilder.new
35+
output = OutputBuilder.new(entity)
3636

3737
normalized_exposures(entity, new_options).each_with_object(output) do |exposure, out|
3838
exposure.with_attr_path(entity, new_options) do
@@ -46,7 +46,7 @@ def valid_value_for(key, entity, options)
4646
new_options = nesting_options_for(options)
4747

4848
result = nil
49-
normalized_exposures(entity, new_options).select { |e| e.key == key }.each do |exposure|
49+
normalized_exposures(entity, new_options).select { |e| e.key(entity) == key }.each do |exposure|
5050
exposure.with_attr_path(entity, new_options) do
5151
result = exposure.valid_value(entity, new_options)
5252
end
@@ -56,7 +56,7 @@ def valid_value_for(key, entity, options)
5656

5757
def serializable_value(entity, options)
5858
new_options = nesting_options_for(options)
59-
output = OutputBuilder.new
59+
output = OutputBuilder.new(entity)
6060

6161
normalized_exposures(entity, new_options).each_with_object(output) do |exposure, out|
6262
exposure.with_attr_path(entity, new_options) do
@@ -67,9 +67,9 @@ def serializable_value(entity, options)
6767
end
6868

6969
# if we have any nesting exposures with the same name.
70-
# delegate :deep_complex_nesting?, to: :nested_exposures
71-
def deep_complex_nesting?
72-
nested_exposures.deep_complex_nesting?
70+
# delegate :deep_complex_nesting?(entity), to: :nested_exposures
71+
def deep_complex_nesting?(entity)
72+
nested_exposures.deep_complex_nesting?(entity)
7373
end
7474

7575
private
@@ -92,15 +92,15 @@ def easy_normalized_exposures(entity, options)
9292

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

9797
table = nested_exposures.each_with_object({}) do |exposure, output|
9898
should_expose = exposure.with_attr_path(entity, options) do
9999
exposure.should_expose?(entity, options)
100100
end
101101
next unless should_expose
102-
output[exposure.key] ||= []
103-
output[exposure.key] << exposure
102+
output[exposure.key(entity)] ||= []
103+
output[exposure.key(entity)] << exposure
104104
end
105105
table.map do |key, exposures|
106106
last_exposure = exposures.last
@@ -113,7 +113,7 @@ def normalized_exposures(entity, options)
113113
end
114114
new_nested_exposures = nesting_tail.flat_map(&:nested_exposures)
115115
NestingExposure.new(key, {}, [], new_nested_exposures).tap do |new_exposure|
116-
new_exposure.instance_variable_set(:@deep_complex_nesting, true) if nesting_tail.any?(&:deep_complex_nesting?)
116+
new_exposure.instance_variable_set(:@deep_complex_nesting, true) if nesting_tail.any? { |exposure| exposure.deep_complex_nesting?(entity) }
117117
end
118118
else
119119
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
@@ -53,10 +53,13 @@ def #{name}(*args, &block)
5353
end
5454

5555
# Determine if we have any nesting exposures with the same name.
56-
def deep_complex_nesting?
56+
def deep_complex_nesting?(entity)
5757
if @deep_complex_nesting.nil?
5858
all_nesting = select(&:nesting?)
59-
@deep_complex_nesting = all_nesting.group_by(&:key).any? { |_key, exposures| exposures.length > 1 }
59+
@deep_complex_nesting =
60+
all_nesting
61+
.group_by { |exposure| exposure.key(entity) }
62+
.any? { |_key, exposures| exposures.length > 1 }
6063
else
6164
@deep_complex_nesting
6265
end

lib/grape_entity/exposure/nesting_exposure/output_builder.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ class Entity
55
module Exposure
66
class NestingExposure
77
class OutputBuilder < SimpleDelegator
8-
def initialize
8+
def initialize(entity)
9+
@entity = entity
910
@output_hash = {}
1011
@output_collection = []
1112
end
@@ -20,7 +21,7 @@ def add(exposure, result)
2021
return unless result
2122
@output_hash.merge! result, &merge_strategy(exposure.for_merge)
2223
else
23-
@output_hash[exposure.key] = result
24+
@output_hash[exposure.key(@entity)] = result
2425
end
2526
end
2627

lib/grape_entity/exposure/represent_exposure.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def ==(other)
2323
end
2424

2525
def value(entity, options)
26-
new_options = options.for_nesting(key)
26+
new_options = options.for_nesting(key(entity))
2727
using_class.represent(@subexposure.value(entity, options), new_options)
2828
end
2929

spec/grape_entity/entity_spec.rb

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

139139
it 'represents the exposure as a hash of its nested.root_exposures' do
@@ -498,7 +498,7 @@ class Parent < Person
498498
end
499499

500500
exposure = subject.find_exposure(:awesome_thing)
501-
expect(exposure.key).to eq :extra_smooth
501+
expect(exposure.key(subject)).to eq :extra_smooth
502502
end
503503

504504
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
@@ -5,11 +5,11 @@
55
describe Grape::Entity::Exposure::NestingExposure::NestedExposures do
66
subject(:nested_exposures) { described_class.new([]) }
77

8-
describe '#deep_complex_nesting?' do
8+
describe '#deep_complex_nesting?(entity)' do
99
it 'is reset when additional exposure is added' do
1010
subject << Grape::Entity::Exposure.new(:x, {})
1111
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
12-
subject.deep_complex_nesting?
12+
subject.deep_complex_nesting?(subject)
1313
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
1414
subject << Grape::Entity::Exposure.new(:y, {})
1515
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -18,7 +18,7 @@
1818
it 'is reset when exposure is deleted' do
1919
subject << Grape::Entity::Exposure.new(:x, {})
2020
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
21-
subject.deep_complex_nesting?
21+
subject.deep_complex_nesting?(subject)
2222
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
2323
subject.delete_by(:x)
2424
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
@@ -27,7 +27,7 @@
2727
it 'is reset when exposures are cleared' do
2828
subject << Grape::Entity::Exposure.new(:x, {})
2929
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil
30-
subject.deep_complex_nesting?
30+
subject.deep_complex_nesting?(subject)
3131
expect(subject.instance_variable_get(:@deep_complex_nesting)).to_not be_nil
3232
subject.clear
3333
expect(subject.instance_variable_get(:@deep_complex_nesting)).to be_nil

0 commit comments

Comments
 (0)