hashie 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +28 -8
- data/VERSION +1 -1
- data/hashie.gemspec +7 -4
- data/lib/hashie.rb +2 -1
- data/lib/hashie/clash.rb +86 -0
- data/spec/hashie/clash_spec.rb +42 -0
- metadata +21 -9
data/README.rdoc
CHANGED
@@ -4,14 +4,8 @@ Hashie is a growing collection of tools that extend Hashes and make
|
|
4
4
|
them more useful.
|
5
5
|
|
6
6
|
== Installation
|
7
|
-
|
8
|
-
Hashie is a gem and is available on Gemcutter. If you don't have Gemcutter,
|
9
|
-
install it:
|
10
|
-
|
11
|
-
gem install gemcutter
|
12
|
-
gem tumble
|
13
7
|
|
14
|
-
|
8
|
+
Hashie is available as a RubyGem:
|
15
9
|
|
16
10
|
gem install hashie
|
17
11
|
|
@@ -62,7 +56,33 @@ can set defaults for each property.
|
|
62
56
|
p = Person.new(:name => "Bob")
|
63
57
|
p.name # => 'Bob'
|
64
58
|
p.occupation # => 'Rubyist'
|
65
|
-
|
59
|
+
|
60
|
+
== Clash
|
61
|
+
|
62
|
+
Clash is a Chainable Lazy Hash that allows you to easily construct
|
63
|
+
complex hashes using method notation chaining. This will allow you
|
64
|
+
to use a more action-oriented approach to building options hashes.
|
65
|
+
|
66
|
+
Essentially, a Clash is a generalized way to provide much of the same
|
67
|
+
kind of "chainability" that libraries like Arel or Rails 2.x's named_scopes
|
68
|
+
provide.
|
69
|
+
|
70
|
+
=== Example
|
71
|
+
|
72
|
+
c = Hashie::Clash.new
|
73
|
+
c.where(:abc => 'def').order(:created_at)
|
74
|
+
c # => {:where => {:abc => 'def}, :order => :created_at}
|
75
|
+
|
76
|
+
# You can also use bang notation to chain into sub-hashes,
|
77
|
+
# jumping back up the chain with _end!
|
78
|
+
c = Hashie::Clash.new
|
79
|
+
c.where!.abc('def').ghi(123)._end!.order(:created_at)
|
80
|
+
c # => {:where => {:abc => 'def', :ghi => 123}, :order => :created_at}
|
81
|
+
|
82
|
+
# Multiple hashes are merged automatically
|
83
|
+
c = Hashie::Clash.new
|
84
|
+
c.where(:abc => 'def').where(:hgi => 123)
|
85
|
+
c # => {:where => {:abc => 'def', :hgi => 123}}
|
66
86
|
|
67
87
|
== Note on Patches/Pull Requests
|
68
88
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/hashie.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hashie}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Bleigh"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-03-05}
|
13
13
|
s.description = %q{Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).}
|
14
14
|
s.email = %q{michael@intridea.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,10 +25,12 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"hashie.gemspec",
|
27
27
|
"lib/hashie.rb",
|
28
|
+
"lib/hashie/clash.rb",
|
28
29
|
"lib/hashie/dash.rb",
|
29
30
|
"lib/hashie/hash.rb",
|
30
31
|
"lib/hashie/hash_extensions.rb",
|
31
32
|
"lib/hashie/mash.rb",
|
33
|
+
"spec/hashie/clash_spec.rb",
|
32
34
|
"spec/hashie/dash_spec.rb",
|
33
35
|
"spec/hashie/hash_spec.rb",
|
34
36
|
"spec/hashie/mash_spec.rb",
|
@@ -38,10 +40,11 @@ Gem::Specification.new do |s|
|
|
38
40
|
s.homepage = %q{http://github.com/intridea/hashie}
|
39
41
|
s.rdoc_options = ["--charset=UTF-8"]
|
40
42
|
s.require_paths = ["lib"]
|
41
|
-
s.rubygems_version = %q{1.3.
|
43
|
+
s.rubygems_version = %q{1.3.6}
|
42
44
|
s.summary = %q{Your friendly neighborhood hash toolkit.}
|
43
45
|
s.test_files = [
|
44
|
-
"spec/hashie/
|
46
|
+
"spec/hashie/clash_spec.rb",
|
47
|
+
"spec/hashie/dash_spec.rb",
|
45
48
|
"spec/hashie/hash_spec.rb",
|
46
49
|
"spec/hashie/mash_spec.rb",
|
47
50
|
"spec/spec_helper.rb"
|
data/lib/hashie.rb
CHANGED
data/lib/hashie/clash.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'hashie/hash'
|
2
|
+
|
3
|
+
module Hashie
|
4
|
+
#
|
5
|
+
# A Clash is a "Chainable Lazy Hash". Inspired by libraries such as Arel,
|
6
|
+
# a Clash allows you to chain together method arguments to build a
|
7
|
+
# hash, something that's especially useful if you're doing something
|
8
|
+
# like constructing a complex options hash. Here's a basic example:
|
9
|
+
#
|
10
|
+
# c = Hashie::Clash.new.conditions(:foo => 'bar').order(:created_at)
|
11
|
+
# c # => {:conditions => {:foo => 'bar'}, :order => :created_at}
|
12
|
+
#
|
13
|
+
# Clash provides another way to create sub-hashes by using bang notation.
|
14
|
+
# You can dive into a sub-hash by providing a key with a bang and dive
|
15
|
+
# back out again with the _end! method. Example:
|
16
|
+
#
|
17
|
+
# c = Hashie::Clash.new.conditions!.foo('bar').baz(123)._end!.order(:created_at)
|
18
|
+
# c # => {:conditions => {:foo => 'bar', :baz => 123}, :order => :created_at}
|
19
|
+
#
|
20
|
+
# Because the primary functionality of Clash is to build options objects,
|
21
|
+
# all keys are converted to symbols since many libraries expect symbols explicitly
|
22
|
+
# for keys.
|
23
|
+
#
|
24
|
+
class Clash < ::Hash
|
25
|
+
class ChainError < ::StandardError; end
|
26
|
+
# The parent Clash if this Clash was created via chaining.
|
27
|
+
attr_reader :_parent
|
28
|
+
|
29
|
+
# Initialize a new clash by passing in a Hash to
|
30
|
+
# convert and, optionally, the parent to which this
|
31
|
+
# Clash is chained.
|
32
|
+
def initialize(other_hash = {}, parent = nil)
|
33
|
+
@_parent = parent
|
34
|
+
other_hash.each_pair do |k, v|
|
35
|
+
self[k.to_sym] = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Jump back up a level if you are using bang method
|
40
|
+
# chaining. For example:
|
41
|
+
#
|
42
|
+
# c = Hashie::Clash.new.foo('bar')
|
43
|
+
# c.baz!.foo(123) # => c[:baz]
|
44
|
+
# c.baz!._end! # => c
|
45
|
+
def _end!
|
46
|
+
self._parent
|
47
|
+
end
|
48
|
+
|
49
|
+
def id(*args) #:nodoc:
|
50
|
+
method_missing(:id, *args)
|
51
|
+
end
|
52
|
+
|
53
|
+
def merge_store(key, *args) #:nodoc:
|
54
|
+
case args.length
|
55
|
+
when 1
|
56
|
+
val = args.first
|
57
|
+
val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
|
58
|
+
else
|
59
|
+
val = args
|
60
|
+
end
|
61
|
+
|
62
|
+
self[key.to_sym] = val
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(name, *args) #:nodoc:
|
67
|
+
name = name.to_s
|
68
|
+
if name.match(/!$/) && args.empty?
|
69
|
+
key = name[0...-1].to_sym
|
70
|
+
|
71
|
+
if self[key].nil?
|
72
|
+
self[key] = Clash.new({}, self)
|
73
|
+
elsif self[key].is_a?(::Hash) && !self[key].is_a?(Clash)
|
74
|
+
self[key] = Clash.new(self[key], self)
|
75
|
+
else
|
76
|
+
raise ChainError, "Tried to chain into a non-hash key."
|
77
|
+
end
|
78
|
+
|
79
|
+
self[key]
|
80
|
+
elsif args.any?
|
81
|
+
key = name.to_sym
|
82
|
+
self.merge_store(key, *args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Hashie::Clash do
|
4
|
+
before do
|
5
|
+
@c = Hashie::Clash.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should be able to set an attribute via method_missing' do
|
9
|
+
@c.foo('bar')
|
10
|
+
@c[:foo].should == 'bar'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be able to set multiple attributes' do
|
14
|
+
@c.foo('bar').baz('wok')
|
15
|
+
@c.should == {:foo => 'bar', :baz => 'wok'}
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should convert multiple arguments into an array' do
|
19
|
+
@c.foo(1, 2, 3)
|
20
|
+
@c[:foo].should == [1,2,3]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be able to use bang notation to create a new Clash on a key' do
|
24
|
+
@c.foo!
|
25
|
+
@c[:foo].should be_kind_of(Hashie::Clash)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should be able to chain onto the new Clash when using bang notation' do
|
29
|
+
@c.foo!.bar('abc').baz(123)
|
30
|
+
@c.should == {:foo => {:bar => 'abc', :baz => 123}}
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should be able to jump back up to the parent in the chain with #_end!' do
|
34
|
+
@c.foo!.bar('abc')._end!.baz(123)
|
35
|
+
@c.should == {:foo => {:bar => 'abc'}, :baz => 123}
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should merge rather than replace existing keys' do
|
39
|
+
@c.where(:abc => 'def').where(:hgi => 123)
|
40
|
+
@c.should == {:where => {:abc => 'def', :hgi => 123}}
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Michael Bleigh
|
@@ -9,19 +14,21 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-05 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
23
29
|
version: "0"
|
24
|
-
|
30
|
+
type: :development
|
31
|
+
version_requirements: *id001
|
25
32
|
description: Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).
|
26
33
|
email: michael@intridea.com
|
27
34
|
executables: []
|
@@ -40,10 +47,12 @@ files:
|
|
40
47
|
- VERSION
|
41
48
|
- hashie.gemspec
|
42
49
|
- lib/hashie.rb
|
50
|
+
- lib/hashie/clash.rb
|
43
51
|
- lib/hashie/dash.rb
|
44
52
|
- lib/hashie/hash.rb
|
45
53
|
- lib/hashie/hash_extensions.rb
|
46
54
|
- lib/hashie/mash.rb
|
55
|
+
- spec/hashie/clash_spec.rb
|
47
56
|
- spec/hashie/dash_spec.rb
|
48
57
|
- spec/hashie/hash_spec.rb
|
49
58
|
- spec/hashie/mash_spec.rb
|
@@ -62,22 +71,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
71
|
requirements:
|
63
72
|
- - ">="
|
64
73
|
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
65
76
|
version: "0"
|
66
|
-
version:
|
67
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
78
|
requirements:
|
69
79
|
- - ">="
|
70
80
|
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
71
83
|
version: "0"
|
72
|
-
version:
|
73
84
|
requirements: []
|
74
85
|
|
75
86
|
rubyforge_project:
|
76
|
-
rubygems_version: 1.3.
|
87
|
+
rubygems_version: 1.3.6
|
77
88
|
signing_key:
|
78
89
|
specification_version: 3
|
79
90
|
summary: Your friendly neighborhood hash toolkit.
|
80
91
|
test_files:
|
92
|
+
- spec/hashie/clash_spec.rb
|
81
93
|
- spec/hashie/dash_spec.rb
|
82
94
|
- spec/hashie/hash_spec.rb
|
83
95
|
- spec/hashie/mash_spec.rb
|