summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Doubrovkine (dB.) @dblockdotorg <dblock@dblock.org>2015-10-27 11:28:43 -0700
committerDaniel Doubrovkine (dB.) @dblockdotorg <dblock@dblock.org>2015-10-27 11:28:43 -0700
commitc71e4fd084635ccf37e3f2a63efd20b244147705 (patch)
tree18cdc8558e8b925abcdf08a57685274bf1336fef
parentb65b849aec38805c88340dbb0b312460f3f4c2ce (diff)
parentb2acb098aa8fa928b54815ace2c40922e24d1f64 (diff)
downloadhashie-c71e4fd084635ccf37e3f2a63efd20b244147705.tar.gz
Merge pull request #321 from luislavena/bk-240-clash-fixes
Clash: multiple bang notation calls
-rw-r--r--CHANGELOG.md1
-rw-r--r--lib/hashie/clash.rb23
-rw-r--r--spec/hashie/clash_spec.rb26
3 files changed, 37 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31a47ed..c2464b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
* [#317](https://github.com/intridea/hashie/pull/317): Ensure `Hashie::Extensions::MethodQuery` methods return boolean values - [@michaelherold](https://github.com/michaelherold).
* [#319](https://github.com/intridea/hashie/pull/319): Fix a regression from 3.4.1 where `Hashie::Extensions::DeepFind` is no longer indifference-aware - [@michaelherold](https://github.com/michaelherold).
+* [#240](https://github.com/intridea/hashie/pull/240): Fixed nesting twice with Clash keys - [@bartoszkopinski](https://github.com/bartoszkopinski).
* Your contribution here.
## 3.4.3 (10/25/2015)
diff --git a/lib/hashie/clash.rb b/lib/hashie/clash.rb
index 4bb755e..945c146 100644
--- a/lib/hashie/clash.rb
+++ b/lib/hashie/clash.rb
@@ -54,7 +54,7 @@ module Hashie
case args.length
when 1
val = args.first
- val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
+ val = self.class.new(self[key]).merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
else
val = args
end
@@ -64,22 +64,23 @@ module Hashie
end
def method_missing(name, *args) #:nodoc:
- name = name.to_s
- if name.match(/!$/) && args.empty?
+ if args.empty? && name.to_s.end_with?('!')
key = name[0...-1].to_sym
- if self[key].nil?
- self[key] = Clash.new({}, self)
- elsif self[key].is_a?(::Hash) && !self[key].is_a?(Clash)
- self[key] = Clash.new(self[key], self)
+ case self[key]
+ when NilClass
+ self[key] = self.class.new({}, self)
+ when Clash
+ self[key]
+ when Hash
+ self[key] = self.class.new(self[key], self)
else
fail ChainError, 'Tried to chain into a non-hash key.'
end
-
- self[key]
elsif args.any?
- key = name.to_sym
- merge_store(key, *args)
+ merge_store(name, *args)
+ else
+ super
end
end
end
diff --git a/spec/hashie/clash_spec.rb b/spec/hashie/clash_spec.rb
index e30dd5c..6212a84 100644
--- a/spec/hashie/clash_spec.rb
+++ b/spec/hashie/clash_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
describe Hashie::Clash do
- subject { Hashie::Clash.new }
-
it 'is able to set an attribute via method_missing' do
subject.foo('bar')
expect(subject[:foo]).to eq 'bar'
@@ -45,4 +43,28 @@ describe Hashie::Clash do
expect(subject[:foo]).to be_nil
expect(subject[:hello]).to be_nil
end
+
+ it 'merges multiple bang notation calls' do
+ subject.where!.foo(123)
+ subject.where!.bar(321)
+ expect(subject).to eq(where: { foo: 123, bar: 321 })
+ end
+
+ it 'raises an exception when method is missing' do
+ expect { subject.boo }.to raise_error(NoMethodError)
+ end
+
+ describe 'when inherited' do
+ subject { Class.new(described_class).new }
+
+ it 'bang nodes are instances of a subclass' do
+ subject.where!.foo(123)
+ expect(subject[:where]).to be_instance_of(subject.class)
+ end
+
+ it 'merged nodes are instances of a subclass' do
+ subject.where(abc: 'def').where(hgi: 123)
+ expect(subject[:where]).to be_instance_of(subject.class)
+ end
+ end
end