diff options
author | Michael Herold <michael.j.herold+github@gmail.com> | 2014-08-24 12:03:32 -0500 |
---|---|---|
committer | Michael Herold <michael.j.herold+github@gmail.com> | 2014-08-24 12:03:32 -0500 |
commit | 976c689632ea0d9538cfa840e5f777d2f3d054c8 (patch) | |
tree | ef8b27c22c2d01aef97676642dc11d53a4bce1d7 | |
parent | 65dd4496ea86d0a71b190a58038d1955f19ba84a (diff) | |
parent | 57a0ffb6786057af0129ecc0a0ea06ad4be9c9e6 (diff) | |
download | hashie-976c689632ea0d9538cfa840e5f777d2f3d054c8.tar.gz |
Merge pull request #212 from dblock/69-multiple-properties-in-trash
Fix #69: multiple property assignments in Trash.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | lib/hashie/trash.rb | 38 | ||||
-rw-r--r-- | spec/hashie/trash_spec.rb | 25 |
3 files changed, 54 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e0e33a4..717a756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#206](http://github.com/intridea/hashie/pull/206): Fixed stack overflow from repetitively including coercion in subclasses - [@michaelherold](https://github.com/michaelherold). * [#207](http://github.com/intridea/hashie/pull/207): Fixed inheritance of transformations in Trash - [@fobocaster](https://github.com/fobocaster). * [#209](http://github.com/intridea/hashie/pull/209): Added Hashie::Extensions::DeepFind - [@michaelherold](https://github.com/michaelherold). +* [#69](https://github.com/intridea/hashie/pull/69): Fixed regression in assigning multiple properties in Hashie::Trash - [@michaelherold](https://github.com/michaelherold), [@einzige](https://github.com/einzige), [@dblock](https://github.com/dblock). * Your contribution here. ## 3.2.0 (7/10/2014) diff --git a/lib/hashie/trash.rb b/lib/hashie/trash.rb index 204b0d7..dbf4dae 100644 --- a/lib/hashie/trash.rb +++ b/lib/hashie/trash.rb @@ -26,11 +26,13 @@ module Hashie fail ArgumentError, "Property name (#{property_name}) and :from option must not be the same" end - translations[options[:from]] = property_name + translations_hash[options[:from]] ||= {} + translations_hash[options[:from]][property_name] = options[:with] || options[:transform_with] define_method "#{options[:from]}=" do |val| - with = options[:with] || options[:transform_with] - self[property_name] = with.respond_to?(:call) ? with.call(val) : val + self.class.translations_hash[options[:from]].each do |name, with| + self[name] = with.respond_to?(:call) ? with.call(val) : val + end end else if options[:transform_with].respond_to? :call @@ -40,15 +42,15 @@ module Hashie end class << self - attr_reader :transforms, :translations + attr_reader :transforms, :translations_hash end instance_variable_set('@transforms', {}) - instance_variable_set('@translations', {}) + instance_variable_set('@translations_hash', {}) def self.inherited(klass) super klass.instance_variable_set('@transforms', transforms.dup) - klass.instance_variable_set('@translations', translations.dup) + klass.instance_variable_set('@translations_hash', translations_hash.dup) end # Set a value on the Dash in a Hash-like way. Only works @@ -68,7 +70,7 @@ module Hashie end def self.translation_exists?(name) - translations.key? name + translations_hash.key? name end def self.transformation_exists?(name) @@ -81,8 +83,26 @@ module Hashie private + def self.translations + @translations ||= begin + h = {} + translations_hash.each do |(property_name, property_translations)| + h[property_name] = property_translations.size > 1 ? property_translations.keys : property_translations.keys.first + end + h + end + end + def self.inverse_translations - @inverse_translations ||= Hash[translations.map(&:reverse)] + @inverse_translations ||= begin + h = {} + translations_hash.each do |(property_name, property_translations)| + property_translations.keys.each do |k| + h[k] = property_name + end + end + h + end end # Raises an NoMethodError if the property doesn't exist @@ -98,7 +118,7 @@ module Hashie def initialize_attributes(attributes) return unless attributes attributes_copy = attributes.dup.delete_if do |k, v| - if self.class.translations.include?(k) + if self.class.translations_hash.include?(k) self[k] = v true end diff --git a/spec/hashie/trash_spec.rb b/spec/hashie/trash_spec.rb index e844093..7bb174f 100644 --- a/spec/hashie/trash_spec.rb +++ b/spec/hashie/trash_spec.rb @@ -29,7 +29,7 @@ describe Hashie::Trash do end it 'maintains translations hash mapping from the original to the translated name' do - expect(TrashTest.translations[:firstName]).to eq :first_name + expect(TrashTest.translations[:firstName]).to eq(:first_name) end it 'maintains inverse translations hash mapping from the translated to the original name' do @@ -134,6 +134,29 @@ describe Hashie::Trash do end end + describe 'translating multiple properties using a proc' do + class SomeDataModel < Hashie::Trash + property :value_a, from: :config, with: ->(config) { config.a } + property :value_b, from: :config, with: ->(config) { config.b } + end + + ConfigDataModel = Struct.new(:a, :b) + + subject { SomeDataModel.new(config: ConfigDataModel.new('value in a', 'value in b')) } + + it 'translates the first key' do + expect(subject.value_a).to eq 'value in a' + end + + it 'translates the second key' do + expect(subject.value_b).to eq 'value in b' + end + + it 'maintains translations hash mapping from the original to the translated name' do + expect(SomeDataModel.translations).to eq(config: [:value_a, :value_b]) + end + end + describe 'uses with or transform_with interchangeably' do class TrashLambdaTestTransformWith < Hashie::Trash property :first_name, from: :firstName, transform_with: ->(value) { value.reverse } |