hashie 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- Then you can install Hashie:
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.8
1
+ 0.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hashie}
8
- s.version = "0.1.8"
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-01-14}
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.5}
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/dash_spec.rb",
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"
@@ -1,4 +1,5 @@
1
1
  require 'hashie/hash_extensions'
2
2
  require 'hashie/hash'
3
3
  require 'hashie/mash'
4
- require 'hashie/dash'
4
+ require 'hashie/dash'
5
+ require 'hashie/clash'
@@ -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
- version: 0.1.8
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-01-14 00:00:00 -05:00
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
- type: :development
18
- version_requirement:
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
- version:
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.5
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