Skip to content

Commit

Permalink
Merge pull request #555 from toptal/fix-value-symbol
Browse files Browse the repository at this point in the history
Handle symbol or string field values correctly
  • Loading branch information
pyromaniac authored Aug 6, 2017
2 parents 4311e42 + 56dddfb commit f8611ad
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
18 changes: 11 additions & 7 deletions lib/chewy/fields/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,26 @@ def compose(*objects)
def evaluate(objects)
object = objects.first

if value && value.is_a?(Proc)
if value.is_a?(Proc)
if value.arity.zero?
object.instance_exec(&value)
elsif value.arity < 0
value.call(*object)
else
value.call(*objects.first(value.arity))
end
elsif object.is_a?(Hash)
if object.key?(name)
object[name]
else
message = value.is_a?(Symbol) || value.is_a?(String) ? value.to_sym : name

if object.is_a?(Hash)
if object.key?(message)
object[message]
else
object[message.to_s]
end
else
object[name.to_s]
object.send(message)
end
else
object.send(name)
end
end

Expand Down
10 changes: 6 additions & 4 deletions lib/chewy/type/witchcraft.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,16 @@ def non_proc_values(field, nesting)
(if #{object}.is_a?(Hash)
{
#{non_proc_fields.map do |f|
fetcher = "#{object}.has_key?(:#{f.name}) ? #{object}[:#{f.name}] : #{object}['#{f.name}']"
key_name = f.value.is_a?(Symbol) || f.value.is_a?(String) ? f.value : f.name
fetcher = "#{object}.has_key?(:#{key_name}) ? #{object}[:#{key_name}] : #{object}['#{key_name}']"
"'#{f.name}'.freeze => #{composed_value(f, fetcher, nesting)}"
end.join(', ')}
}
else
{
#{non_proc_fields.map do |f|
"'#{f.name}'.freeze => #{composed_value(f, "#{object}.#{f.name}", nesting)}"
method_name = f.value.is_a?(Symbol) || f.value.is_a?(String) ? f.value : f.name
"'#{f.name}'.freeze => #{composed_value(f, "#{object}.#{method_name}", nesting)}"
end.join(', ')}
}
end)
Expand Down Expand Up @@ -137,7 +139,7 @@ def proc_values(field, nesting)

def non_proc_fields_for(parent, nesting)
return [] unless parent
fields = (parent.children || []).reject { |field| field.value && field.value.is_a?(Proc) }
fields = (parent.children || []).reject { |field| field.value.is_a?(Proc) }

if nesting.zero? && @fields.present?
fields.select { |f| @fields.include?(f.name) }
Expand All @@ -148,7 +150,7 @@ def non_proc_fields_for(parent, nesting)

def proc_fields_for(parent, nesting)
return [] unless parent
fields = (parent.children || []).select { |field| field.value && field.value.is_a?(Proc) }
fields = (parent.children || []).select { |field| field.value.is_a?(Proc) }

if nesting.zero? && @fields.present?
fields.select { |f| @fields.include?(f.name) }
Expand Down
2 changes: 2 additions & 0 deletions spec/chewy/fields/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
specify { expect(field.compose(double(value: 'hello'))).to eq(name: 'hello') }
specify { expect(field.compose(double(value: %w[hello world]))).to eq(name: %w[hello world]) }

specify { expect(described_class.new(:name, value: :last_name).compose(double(last_name: 'hello'))).to eq(name: 'hello') }
specify { expect(described_class.new(:name, value: :last_name).compose('last_name' => 'hello')).to eq(name: 'hello') }
specify { expect(described_class.new(:name).compose(double(name: 'hello'))).to eq(name: 'hello') }
specify { expect(described_class.new(:false_value).compose(false_value: false)).to eq(false_value: false) }
specify { expect(described_class.new(:true_value).compose(true_value: true)).to eq(true_value: true) }
Expand Down
16 changes: 16 additions & 0 deletions spec/chewy/type/witchcraft_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,5 +212,21 @@ def self.custom_value(field)
specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) }
end
end

context 'symbol value' do
mapping do
field :name, value: :last_name
end

context do
let(:object) { double(last_name: 'Name') }
specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) }
end

context do
let(:object) { {'last_name' => 'Name'} }
specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) }
end
end
end
end

0 comments on commit f8611ad

Please sign in to comment.