hash-ninja 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +6 -0
- data/Rakefile +1 -0
- data/hashninja.gemspec +21 -0
- data/lib/hash_ninja.rb +10 -0
- data/lib/hash_ninja/active_hash.rb +127 -0
- data/lib/hash_ninja/core_ext.rb +50 -0
- data/lib/hash_ninja/hash_attr_reader.rb +37 -0
- data/lib/hash_ninja/version.rb +5 -0
- data/spec/hash_ninja/active_hash_spec.rb +26 -0
- data/spec/hash_ninja/core_ext_spec.rb +86 -0
- data/spec/hash_ninja/hash_attr_reader_spec.rb +66 -0
- data/spec/hash_ninja/usage_spec.rb +46 -0
- metadata +78 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/hashninja.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "hash_ninja/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "hash-ninja"
|
7
|
+
s.version = HashNinja::VERSION
|
8
|
+
s.authors = ["Kazuhiro Sera"]
|
9
|
+
s.email = ["seratch@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/seratch/hash-ninja"
|
11
|
+
s.summary = %q{Hash toolkit for Ruby ninja}
|
12
|
+
s.description = %q{Hash toolkit for Ruby ninja}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_runtime_dependency "activesupport"
|
20
|
+
|
21
|
+
end
|
data/lib/hash_ninja.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "hash_ninja"
|
4
|
+
require "active_support/core_ext/hash/keys"
|
5
|
+
|
6
|
+
module HashNinja
|
7
|
+
|
8
|
+
# Hash with extended ActiveSupport
|
9
|
+
#
|
10
|
+
# See also {active_support/core_ext/hash/keys}[http://as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
|
11
|
+
module ActiveHash
|
12
|
+
|
13
|
+
# Applies ActiveSupport::Inflector.underscore to all the Hash#keys destructively.
|
14
|
+
# Keys should be either Symbol or String.
|
15
|
+
#
|
16
|
+
# ==== Examples
|
17
|
+
# hash = {:rubyOnRails => 'http://rubyonrails.org/'}
|
18
|
+
# has.activate!.underscore_keys! # => {:ruby_on_rails => 'http://rubyonrails.org/'}
|
19
|
+
def underscore_keys!
|
20
|
+
self.keys.each do |key|
|
21
|
+
value = delete(key)
|
22
|
+
if key.is_a? String
|
23
|
+
self[key.underscore] = value
|
24
|
+
elsif key.is_a? Symbol
|
25
|
+
self[key.to_s.underscore.to_sym] = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Applies ActiveSupport::Inflector#classify to all the Hash#keys destructively.
|
32
|
+
# Keys should be either Symbol or String.
|
33
|
+
#
|
34
|
+
# ==== Examples
|
35
|
+
# hash = {:ruby_on_rails => 'http://rubyonrails.org/'}
|
36
|
+
# has.activate!.classify_keys! # => {:RubyOnRails => 'http://rubyonrails.org/'}
|
37
|
+
def classify_keys!
|
38
|
+
self.keys.each do |key|
|
39
|
+
value = delete(key)
|
40
|
+
if key.is_a? String
|
41
|
+
self[key.classify] = value
|
42
|
+
elsif key.is_a? Symbol
|
43
|
+
self[key.to_s.classify.to_sym] = value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Applies ActiveSupport::Inflector#camelize to all the Hash#keys destructively.
|
49
|
+
# Keys should be either Symbol or String.
|
50
|
+
#
|
51
|
+
# ==== Examples
|
52
|
+
# hash = {:ruby_on_rails => 'http://rubyonrails.org/'}
|
53
|
+
# has.activate!.camelize_keys! # => {:RubyOnRails => 'http://rubyonrails.org/'}
|
54
|
+
def camelize_keys!
|
55
|
+
self.keys.each do |key|
|
56
|
+
value = delete(key)
|
57
|
+
if key.is_a? String
|
58
|
+
self[key.camelize] = value
|
59
|
+
elsif key.is_a? Symbol
|
60
|
+
self[key.to_s.camelize.to_sym] = value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Applies ActiveSupport::Inflector#camelize(:lower) to all the Hash#keys destructively.
|
67
|
+
# Keys should be either Symbol or String.
|
68
|
+
#
|
69
|
+
# ==== Examples
|
70
|
+
# hash = {:ruby_on_rails => 'http://rubyonrails.org/'}
|
71
|
+
# has.activate!.camelize_lower_keys! # => {:rubyOnRails => 'http://rubyonrails.org/'}
|
72
|
+
def camelize_lower_keys!
|
73
|
+
self.keys.each do |key|
|
74
|
+
value = delete(key)
|
75
|
+
if key.is_a? String
|
76
|
+
self[key.camelize(:lower)] = value
|
77
|
+
elsif key.is_a? Symbol
|
78
|
+
self[key.to_s.camelize(:lower).to_sym] = value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Provides the following recursive methods.
|
84
|
+
#
|
85
|
+
# ====
|
86
|
+
# * recursively_camelize_keys!
|
87
|
+
# * recursively_camelize_lower_keys!
|
88
|
+
# * recursively_classify_keys!
|
89
|
+
# * recursively_underscore_keys!
|
90
|
+
def method_missing(name, *args, &block)
|
91
|
+
# provides 'recursively_xxx' methods
|
92
|
+
if name.match(/recursively_/)
|
93
|
+
method_name = name.to_s.sub(/^recursively_/, '')
|
94
|
+
self.public_send(method_name, *args, &block)
|
95
|
+
self.values.each do |value|
|
96
|
+
if value.is_a? Hash
|
97
|
+
value.extend HashNinja::ActiveHash
|
98
|
+
value.public_send(name, *args, &block)
|
99
|
+
elsif value.is_a? Array
|
100
|
+
value.public_send(name, *args, &block)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class Array
|
111
|
+
def method_missing(name, *args, &block)
|
112
|
+
# for ActiveHash#recursively_xxx
|
113
|
+
if name.match(/recursively_/)
|
114
|
+
method_name = name.to_s.sub(/^recursively_/, '')
|
115
|
+
self.each do |value|
|
116
|
+
if value.is_a? Hash
|
117
|
+
value.extend HashNinja::ActiveHash
|
118
|
+
value.public_send(name, *args, &block)
|
119
|
+
elsif value.is_a? Array
|
120
|
+
value.public_send(name, *args, &block)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
self
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "hash_ninja"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
5
|
+
|
6
|
+
module HashNinja
|
7
|
+
module CoreExt
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Hash
|
12
|
+
|
13
|
+
# Updates itself as HashNinja::ActiveHash destructively. 'active_support' will be also applied.
|
14
|
+
def activate!
|
15
|
+
self.extend HashNinja::ActiveHash
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Provides HashNinja::HashAccessor object
|
20
|
+
def to_attr_reader
|
21
|
+
HashNinja::HashAttrReader.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Creates Hash object which contains the readable instance variables of 'obj'.
|
25
|
+
# It's possible to customize the key convention by 'key_strategy'.
|
26
|
+
def self.from_attr(obj, key_strategy = :underscore)
|
27
|
+
hash = {}
|
28
|
+
obj.instance_variables.each do |attr|
|
29
|
+
original_key = attr.to_s.delete('@')
|
30
|
+
case key_strategy
|
31
|
+
when :underscore
|
32
|
+
key = original_key.underscore
|
33
|
+
when :camelize
|
34
|
+
key = original_key.camelize
|
35
|
+
when :camelize_lower
|
36
|
+
key = original_key.camelize(:lower)
|
37
|
+
when :classify
|
38
|
+
key = original_key.classify
|
39
|
+
else
|
40
|
+
key = original_key
|
41
|
+
end
|
42
|
+
begin
|
43
|
+
hash[key.to_sym] = obj.send(original_key.to_sym)
|
44
|
+
rescue NoMethodError => e
|
45
|
+
end
|
46
|
+
end
|
47
|
+
hash
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module HashNinja
|
4
|
+
|
5
|
+
# Provides attr_reader Hash data
|
6
|
+
# ==== Examples
|
7
|
+
# member = {'name'=>'Andy', 'type' => { 'id' => 999, 'name' => 'Guest' }}.to_attr_reader
|
8
|
+
# member.name # => 'Andy'
|
9
|
+
# member.type.id # => 999
|
10
|
+
class HashAttrReader
|
11
|
+
# target Hash object
|
12
|
+
attr_reader :hash
|
13
|
+
|
14
|
+
# The 'hash' should be a Hash object.
|
15
|
+
def initialize(hash)
|
16
|
+
raise "hash should be a Hash object #{hash.to_s}" unless hash.is_a? Hash
|
17
|
+
@hash = hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(name, *args, &block)
|
21
|
+
found = @hash[name] || @hash[name.to_s]
|
22
|
+
if found
|
23
|
+
if found.is_a? Hash
|
24
|
+
found.to_attr_reader
|
25
|
+
else
|
26
|
+
found
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the Hash object held internally
|
32
|
+
def to_hash
|
33
|
+
@hash
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'hash_ninja'
|
5
|
+
|
6
|
+
describe HashNinja::ActiveHash do
|
7
|
+
|
8
|
+
it 'should have #underscore_keys!' do
|
9
|
+
hash = {:rubyOnRails => 'xxx', 'ProgrammingRuby' => {'RubyGems' => 'yyy'}}
|
10
|
+
hash.activate!.underscore_keys!
|
11
|
+
|
12
|
+
hash[:ruby_on_rails].should eq('xxx')
|
13
|
+
hash['programming_ruby'].should eq({'RubyGems' => 'yyy'})
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should have #recursively_underscore_keys!' do
|
17
|
+
hash = {:rubyOnRails => 'aaa', 'ProgrammingRuby' => {:RubyGems => 'bbb', 'rubyMine' => 'ccc'}}
|
18
|
+
hash.activate!.recursively_underscore_keys!
|
19
|
+
|
20
|
+
hash[:ruby_on_rails].should eq('aaa')
|
21
|
+
hash['programming_ruby'].should eq({:ruby_gems => 'bbb', 'ruby_mine' => 'ccc'})
|
22
|
+
hash['programming_ruby'][:ruby_gems].should eq('bbb')
|
23
|
+
hash['programming_ruby']['ruby_mine'].should eq('ccc')
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'hash_ninja'
|
4
|
+
|
5
|
+
describe Hash do
|
6
|
+
|
7
|
+
it 'should have #activate!' do
|
8
|
+
activated = {:first => 'aaa', 'second' => 'bbb'}.activate!
|
9
|
+
activated.is_a?(HashNinja::ActiveHash).should eq(true)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Member
|
13
|
+
attr_accessor :id
|
14
|
+
attr_accessor :name
|
15
|
+
attr_accessor :age
|
16
|
+
|
17
|
+
def initialize(id, name, age)
|
18
|
+
@id = id
|
19
|
+
@name = name
|
20
|
+
@age = age
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Member2Underscore
|
25
|
+
attr_accessor :firstName
|
26
|
+
attr_accessor :lastName
|
27
|
+
|
28
|
+
def initialize(firstName, lastName)
|
29
|
+
@firstName = firstName
|
30
|
+
@lastName = lastName
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Member2Camelize
|
35
|
+
attr_accessor :first_name
|
36
|
+
attr_accessor :last_name
|
37
|
+
|
38
|
+
def initialize(first_name, last_name)
|
39
|
+
@first_name = first_name
|
40
|
+
@last_name = last_name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'shoud have from_attr' do
|
45
|
+
andy = Member.new(123, 'Andy', 20)
|
46
|
+
andy_hash = Hash.from_attr(andy)
|
47
|
+
andy_hash[:id].should eq(123)
|
48
|
+
andy_hash[:name].should eq('Andy')
|
49
|
+
andy_hash[:age].should eq(20)
|
50
|
+
|
51
|
+
brian = Member.new(123, 'Brian', nil)
|
52
|
+
brian_hash = Hash.from_attr(brian)
|
53
|
+
brian_hash[:id].should eq(123)
|
54
|
+
brian_hash[:name].should eq('Brian')
|
55
|
+
brian_hash[:age].should eq(nil)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should have from_attr (underscore)' do
|
59
|
+
m = Member2Underscore.new('Linus', 'Torvalds')
|
60
|
+
hash = Hash.from_attr(m, :underscore)
|
61
|
+
hash[:first_name].should eq('Linus')
|
62
|
+
hash[:last_name].should eq('Torvalds')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should have from_attr (camelize)' do
|
66
|
+
m = Member2Camelize.new('Linus', 'Torvalds')
|
67
|
+
hash = Hash.from_attr(m, :camelize)
|
68
|
+
hash[:FirstName].should eq('Linus')
|
69
|
+
hash[:LastName].should eq('Torvalds')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should have from_attr (camelize_lower)' do
|
73
|
+
m = Member2Camelize.new('Linus', 'Torvalds')
|
74
|
+
hash = Hash.from_attr(m, :camelize_lower)
|
75
|
+
hash[:firstName].should eq('Linus')
|
76
|
+
hash[:lastName].should eq('Torvalds')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should have from_attr (classify)' do
|
80
|
+
m = Member2Camelize.new('Linus', 'Torvalds')
|
81
|
+
hash = Hash.from_attr(m, :classify)
|
82
|
+
hash[:FirstName].should eq('Linus')
|
83
|
+
hash[:LastName].should eq('Torvalds')
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "hash_ninja"
|
4
|
+
|
5
|
+
describe HashNinja::HashAttrReader do
|
6
|
+
|
7
|
+
it 'should work with string keys' do
|
8
|
+
hash = {:something => 'like that', :name => 'hash_ninja'}
|
9
|
+
hash_attr = hash.to_attr_reader
|
10
|
+
|
11
|
+
hash_attr.something.should eq('like that')
|
12
|
+
hash_attr.name.should eq('hash_ninja')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should work with symbol keys' do
|
16
|
+
hash = {:something => 'like that', :name => 'hash_ninja'}
|
17
|
+
hash_attr = hash.to_attr_reader
|
18
|
+
|
19
|
+
hash_attr.something.should eq('like that')
|
20
|
+
hash_attr.name.should eq('hash_ninja')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should work with nested hash' do
|
24
|
+
hash = {
|
25
|
+
:something => 'like that',
|
26
|
+
:nested => {
|
27
|
+
:name => 'hash_ninja',
|
28
|
+
:since => 2012
|
29
|
+
}
|
30
|
+
}
|
31
|
+
hash_attr = hash.to_attr_reader
|
32
|
+
|
33
|
+
hash_attr.something.should eq('like that')
|
34
|
+
hash_attr.nested.name.should eq('hash_ninja')
|
35
|
+
hash_attr.nested.since.should eq(2012)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should work with keys which contains whitespace' do
|
39
|
+
hash = {'contains whitespace' => 'like that'}
|
40
|
+
hash_attr = hash.to_attr_reader
|
41
|
+
|
42
|
+
hash_attr.contains_whitespace.should eq(nil)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should work with string keys' do
|
46
|
+
hash = {'something' => 'like that', 'name' => 'hash_ninja'}
|
47
|
+
hash_attr = hash.to_attr_reader
|
48
|
+
|
49
|
+
hash_attr.something.should eq('like that')
|
50
|
+
hash_attr.name.should eq('hash_ninja')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should work with array' do
|
54
|
+
hash = {
|
55
|
+
'str_array' => ['a', 'b', 'c'],
|
56
|
+
'hash_array' => [{:a => 1}, {:aa => 1, :bb => 2}],
|
57
|
+
'nested' => {'array' => [1, 2, 3]}
|
58
|
+
}
|
59
|
+
hash_attr = hash.to_attr_reader
|
60
|
+
|
61
|
+
hash_attr.str_array.should eq(['a', 'b', 'c'])
|
62
|
+
hash_attr.hash_array.should eq([{:a => 1}, {:aa => 1, :bb => 2}])
|
63
|
+
hash_attr.nested.array.should eq([1, 2, 3])
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'hash_ninja'
|
5
|
+
|
6
|
+
describe HashNinja do
|
7
|
+
|
8
|
+
it 'should work with the Google+ API example data' do
|
9
|
+
google_plus_api_example = <<JSON
|
10
|
+
{
|
11
|
+
"kind": "plus#person",
|
12
|
+
"id": "118051310819094153327",
|
13
|
+
"displayName": "Chirag Shah",
|
14
|
+
"url": "https://plus.google.com/118051310819094153327",
|
15
|
+
"image": {
|
16
|
+
"url": "https://lh5.googleusercontent.com/-XnZDEoiF09Y/AAAAAAAAAAI/AAAAAAAAYCI/7fow4a2UTMU/photo.jpg"
|
17
|
+
}
|
18
|
+
}
|
19
|
+
JSON
|
20
|
+
|
21
|
+
hash = ActiveSupport::JSON.decode(google_plus_api_example)
|
22
|
+
hash.activate!
|
23
|
+
|
24
|
+
hash.recursively_underscore_keys!
|
25
|
+
hash['kind'].should eq('plus#person')
|
26
|
+
hash['id'].should eq('118051310819094153327')
|
27
|
+
hash['display_name'].should eq('Chirag Shah')
|
28
|
+
hash['url'].should eq('https://plus.google.com/118051310819094153327')
|
29
|
+
hash['image']['url'].should eq('https://lh5.googleusercontent.com/-XnZDEoiF09Y/AAAAAAAAAAI/AAAAAAAAYCI/7fow4a2UTMU/photo.jpg')
|
30
|
+
|
31
|
+
hash.recursively_symbolize_keys!
|
32
|
+
hash[:kind].should eq('plus#person')
|
33
|
+
hash[:id].should eq('118051310819094153327')
|
34
|
+
hash[:display_name].should eq('Chirag Shah')
|
35
|
+
hash[:url].should eq('https://plus.google.com/118051310819094153327')
|
36
|
+
hash[:image][:url].should eq('https://lh5.googleusercontent.com/-XnZDEoiF09Y/AAAAAAAAAAI/AAAAAAAAYCI/7fow4a2UTMU/photo.jpg')
|
37
|
+
|
38
|
+
hash_attr = hash.to_attr_reader
|
39
|
+
hash_attr.kind.should eq('plus#person')
|
40
|
+
hash_attr.id.should eq('118051310819094153327')
|
41
|
+
hash_attr.display_name.should eq('Chirag Shah')
|
42
|
+
hash_attr.url.should eq('https://plus.google.com/118051310819094153327')
|
43
|
+
hash_attr.image.url.should eq('https://lh5.googleusercontent.com/-XnZDEoiF09Y/AAAAAAAAAAI/AAAAAAAAYCI/7fow4a2UTMU/photo.jpg')
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hash-ninja
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kazuhiro Sera
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Hash toolkit for Ruby ninja
|
31
|
+
email:
|
32
|
+
- seratch@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- Rakefile
|
40
|
+
- hashninja.gemspec
|
41
|
+
- lib/hash_ninja.rb
|
42
|
+
- lib/hash_ninja/active_hash.rb
|
43
|
+
- lib/hash_ninja/core_ext.rb
|
44
|
+
- lib/hash_ninja/hash_attr_reader.rb
|
45
|
+
- lib/hash_ninja/version.rb
|
46
|
+
- spec/hash_ninja/active_hash_spec.rb
|
47
|
+
- spec/hash_ninja/core_ext_spec.rb
|
48
|
+
- spec/hash_ninja/hash_attr_reader_spec.rb
|
49
|
+
- spec/hash_ninja/usage_spec.rb
|
50
|
+
homepage: https://github.com/seratch/hash-ninja
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.8.21
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Hash toolkit for Ruby ninja
|
74
|
+
test_files:
|
75
|
+
- spec/hash_ninja/active_hash_spec.rb
|
76
|
+
- spec/hash_ninja/core_ext_spec.rb
|
77
|
+
- spec/hash_ninja/hash_attr_reader_spec.rb
|
78
|
+
- spec/hash_ninja/usage_spec.rb
|