tigon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # Get your spec rake tasks working in RSpec 2.0
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Default: run specs.'
6
+ task :default => :spec
7
+
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
11
+ # Put spec opts in a file named .rspec in root
12
+ end
data/lib/tigon.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/tigon/hash_transformer'
2
+ require File.dirname(__FILE__) + '/tigon/hash_extensions'
@@ -0,0 +1,7 @@
1
+ class Hash
2
+ def transform(options = {}, &blk)
3
+ tr = Tigon::HashTransformer.new(self, :exclusive => !!options[:exclusive])
4
+ tr.instance_exec(&blk)
5
+ tr.new_hash
6
+ end
7
+ end
@@ -0,0 +1,77 @@
1
+ module Tigon
2
+ class HashTransformer
3
+ def initialize(hash_or_value, options = {})
4
+ @options = options
5
+ @current_value = hash_or_value
6
+ if @current_value.is_a?(Hash) && !options[:exclusive]
7
+ @new_hash = @current_value
8
+ else
9
+ @new_hash = {}
10
+ end
11
+ end
12
+
13
+ def new_hash
14
+ @new_hash
15
+ end
16
+
17
+ def value
18
+ @current_value
19
+ end
20
+
21
+ def keep(name)
22
+ @new_hash[name] = @current_value[name]
23
+ @new_hash
24
+ end
25
+
26
+ def morph(name, newname = false, options = false, &blk)
27
+ options ||= @options
28
+
29
+ replacement_key = if newname
30
+ newname
31
+ else
32
+ if name.is_a?(String)
33
+ name
34
+ else
35
+ name.last #assumes an array was passed
36
+ end
37
+ end
38
+
39
+ if @current_value.is_a?(Hash) && (@current_value.key?(name) || (name.is_a?(Array) && @current_value.key?(name[0])))
40
+ if name.is_a?(Array)
41
+ current_val = furthest_value_from_hash(name, @current_value)
42
+ else
43
+ current_val = @current_value[name]
44
+ end
45
+
46
+ if block_given?
47
+ @new_hash[replacement_key] = nest_tranformation(current_val, replacement_key, options, blk)
48
+ else
49
+ @new_hash[replacement_key] = current_val
50
+ end
51
+ @new_hash.delete(name) if newname
52
+ end
53
+ @new_hash
54
+ end
55
+
56
+ def nest_tranformation(val, replacement_key, options, blk)
57
+ transformer = self.class.new(val, options)
58
+ transformed_val = transformer.instance_exec(&blk)
59
+
60
+ #preserve values from previous calls to morph
61
+ if transformed_val.is_a?(Hash) && @new_hash[replacement_key]
62
+ transformed_val = transformed_val.merge(@new_hash[replacement_key])
63
+ end
64
+ transformed_val
65
+ end
66
+
67
+ def furthest_value_from_hash(key_array, lookup_hash)
68
+ key_array.reduce(lookup_hash) do |context, k|
69
+ if context.is_a?(Hash)
70
+ context[k]
71
+ else
72
+ context
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module Tigon
2
+ VERSION = "0.0.1"
3
+ end
data/readme.markdown ADDED
@@ -0,0 +1,67 @@
1
+ ### Tigon adds a transform method to Hash, providing a means to rename and merge keys and manipulate their values.
2
+
3
+ ##Installation
4
+ gem install tigon
5
+
6
+ ##Usage
7
+ require 'tigon'
8
+
9
+ r = {
10
+ 'followers_count' => '310000301',
11
+ 'friends_count' => '6',
12
+ 'listed_count' => '6',
13
+ 'default_profile_image' => false,
14
+ 'statuses_count' => '1'
15
+ }.transform(:exclusive => true) do
16
+ morph('followers_count', :friendships) do
17
+ {:followers => value.to_i}
18
+ end
19
+
20
+ morph('friends_count', :friendships) do
21
+ {:following => value.to_i}
22
+ end
23
+
24
+ morph('listed_count', :listed) do
25
+ value.to_i
26
+ end
27
+
28
+ morph('statuses_count', :statuses) do
29
+ value.to_i + 1
30
+ end
31
+ end
32
+
33
+ r == {
34
+ :friendships => {
35
+ :followers => 310000301,
36
+ :following => 6
37
+ },
38
+ :listed => 6,
39
+ :statuses => 2
40
+ } # true
41
+
42
+ ##LICENSE
43
+
44
+ (The MIT License)
45
+
46
+ Copyright © 2011:
47
+
48
+ Max Justus Spransy
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining
51
+ a copy of this software and associated documentation files (the
52
+ ‘Software’), to deal in the Software without restriction, including
53
+ without limitation the rights to use, copy, modify, merge, publish,
54
+ distribute, sublicense, and/or sell copies of the Software, and to
55
+ permit persons to whom the Software is furnished to do so, subject to
56
+ the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be
59
+ included in all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
62
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require File.dirname(__FILE__) + '/../lib/tigon'
3
+
4
+ RSpec.configure do |config|
5
+
6
+ end
@@ -0,0 +1,202 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Hash' do
4
+ context 'transform' do
5
+ it 'takes a block in which you call morph - passing in the name of the key to morph, the new name, and an optional block to further transform the value(s)' do
6
+ h = {
7
+ 'guy' => 'guy',
8
+ 'cool' => {'stuff' => 'neat'},
9
+ 'otherthing' => 'rad411'
10
+ }
11
+
12
+ h.transform do
13
+ morph('cool', :cool) do
14
+ morph('stuff', :stuff) {value.upcase}
15
+ end
16
+ morph('otherthing', :thing) {value.gsub('rad','')}
17
+ end.should == {
18
+ 'guy' => 'guy',
19
+ :cool => {:stuff => 'NEAT'},
20
+ :thing => '411'
21
+ }
22
+ end
23
+
24
+ it 'allows you to call morph without passing a block' do
25
+ h = {
26
+ 'guy' => 'guy',
27
+ 'cool' => {'stuff' => 'neat'},
28
+ 'otherthing' => 'rad411'
29
+ }
30
+
31
+ h.transform do
32
+ morph('cool', :cool)
33
+ end.should == {
34
+ 'guy' => 'guy',
35
+ :cool => {'stuff' => 'neat'},
36
+ 'otherthing' => 'rad411'
37
+ }
38
+ end
39
+
40
+ it 'ignores transformations which are not present in source hash' do
41
+ h = {
42
+ 'guy' => 'guy',
43
+ 'cool' => {'stuff' => 'neat'},
44
+ 'otherthing' => 'rad411'
45
+ }
46
+
47
+ h.transform do
48
+ morph(['cool', 'thing'], :cool)
49
+ morph('rawr', :cool)
50
+ morph('cool', :cool)
51
+ end.should == {
52
+ 'guy' => 'guy',
53
+ :cool => {'stuff' => 'neat'},
54
+ 'otherthing' => 'rad411'
55
+ }
56
+ end
57
+
58
+ it 'allows you to call morph with the name of the current key and a block' do
59
+ h = {
60
+ 'guy' => 'guy',
61
+ 'cool' => {'stuff' => 'neat'},
62
+ 'otherthing' => 'rad411'
63
+ }
64
+ h.transform do
65
+ morph('cool') do
66
+ morph('stuff') do
67
+ value.upcase
68
+ end
69
+ end
70
+ end.should == {
71
+ 'guy' => 'guy',
72
+ 'cool' => {'stuff' => 'NEAT'},
73
+ 'otherthing' => 'rad411'
74
+ }
75
+ end
76
+
77
+ it 'allows you to morph two different keys into the same key' do
78
+ h = {
79
+ 'guy' => 'guy',
80
+ 'cool' => {'stuff' => 'neat'},
81
+ 'otherthing' => 'rad411'
82
+ }
83
+
84
+ h.transform(:exclusive => true) do
85
+ morph('guy', 'neat') do
86
+ {'man' => value}
87
+ end
88
+ morph('cool', 'neat') do
89
+ morph('stuff') do
90
+ value.upcase
91
+ end
92
+ end
93
+ end.should == {
94
+ 'neat' => {
95
+ 'man' => 'guy',
96
+ 'stuff' => 'NEAT'
97
+ }
98
+ }
99
+ end
100
+
101
+ it 'allows you to pass an array to morph subhashes of the value of the key' do
102
+ h = {
103
+ 'guy' => {'man' => 'bro'},
104
+ 'cool' => {
105
+ 'stuff' => 'neat',
106
+ 'run' => 'fast'
107
+ },
108
+ 'otherthing' => {
109
+ 'rad411' => {'cool' => 'neat'}
110
+ },
111
+ 'tools' => {
112
+ 'hammer' => {
113
+ 'rock' => {'stove' => 'iron'}
114
+ }
115
+ }
116
+ }
117
+
118
+ h.transform(:exclusive => true) do
119
+ morph(['cool', 'stuff'], 'neat') do
120
+ {'important' => value.upcase}
121
+ end
122
+
123
+ morph(['cool', 'run'], 'neat') do
124
+ {'run' => value}
125
+ end
126
+
127
+ morph(['otherthing', 'rad411', 'cool'], 'neat') do
128
+ {'critical' => value.upcase + 's'}
129
+ end
130
+
131
+ morph(['guy', 'man'], 'kewl') do
132
+ value.upcase
133
+ end
134
+
135
+ morph(['tools', 'hammer'], 'toolz')
136
+ end.should == {
137
+ 'kewl' => 'BRO',
138
+ 'neat' => {
139
+ 'important' => 'NEAT',
140
+ 'critical' => 'NEATs',
141
+ 'run' => 'fast'
142
+ },
143
+ 'toolz' => {
144
+ 'rock' => {'stove' => 'iron'}
145
+ }
146
+ }
147
+ end
148
+
149
+ it 'allows you to call keep to keep a key if :exclusive is set to true' do
150
+ h = {
151
+ 'guy' => 'guy',
152
+ 'cool' => {'stuff' => 'neat'},
153
+ 'otherthing' => 'rad411'
154
+ }
155
+
156
+ h.transform(:exclusive => true) do
157
+ morph('cool') do
158
+ morph('stuff') do
159
+ value.upcase
160
+ end
161
+ end
162
+ keep('guy')
163
+ end.should == {'guy' => 'guy', 'cool' => {'stuff' => 'NEAT'}}
164
+ end
165
+
166
+ it 'has an :exclusive option which restricts the returned hash to values passed to morph within block' do
167
+ h = {
168
+ 'guy' => 'guy',
169
+ 'cool' => {
170
+ 'stuff' => 'neat',
171
+ 'otherthing' => 'cool',
172
+ 'thingthing' => {
173
+ 't' => 't',
174
+ 'thing' => 'thing'
175
+ }
176
+ },
177
+ 'otherthing' => 'rad411'
178
+ }
179
+
180
+ h.transform(:exclusive => true) do
181
+ morph('cool', :cool) do
182
+ morph('stuff', :stuff) {value.upcase}
183
+ morph('thingthing', :thing, :exclusive => false) do
184
+ morph('thing') do
185
+ value.reverse
186
+ end
187
+ end
188
+ end
189
+ morph('otherthing', :thing) {value.gsub('rad','')}
190
+ end.should == {
191
+ :cool => {
192
+ :stuff => 'NEAT',
193
+ :thing => {
194
+ 'thing' => 'gniht',
195
+ 't' => 't'
196
+ }
197
+ },
198
+ :thing => '411'
199
+ }
200
+ end
201
+ end
202
+ end
data/tigon.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "tigon/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "tigon"
7
+ s.version = Tigon::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Max Justus Spransy"]
10
+ s.email = ["maxjustus@gmail.com"]
11
+ s.homepage = "https://github.com/maxjustus/Tigon"
12
+ s.summary = %q{A simple dsl for hash transformation.}
13
+ s.description = %q{
14
+ Tigon provides a declarative syntax for transforming hashes.
15
+ }
16
+
17
+ s.rubyforge_project = "tigon"
18
+
19
+ s.add_development_dependency 'rspec', '~> 2.5.0'
20
+ s.add_development_dependency 'rake'
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tigon
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Max Justus Spransy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-16 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 2.5.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :development
37
+ version_requirements: *id002
38
+ description: "\n Tigon provides a declarative syntax for transforming hashes. \n "
39
+ email:
40
+ - maxjustus@gmail.com
41
+ executables: []
42
+
43
+ extensions: []
44
+
45
+ extra_rdoc_files: []
46
+
47
+ files:
48
+ - Rakefile
49
+ - lib/tigon.rb
50
+ - lib/tigon/hash_extensions.rb
51
+ - lib/tigon/hash_transformer.rb
52
+ - lib/tigon/version.rb
53
+ - readme.markdown
54
+ - spec/spec_helper.rb
55
+ - spec/unit/hash_transformer_spec.rb
56
+ - tigon.gemspec
57
+ has_rdoc: true
58
+ homepage: https://github.com/maxjustus/Tigon
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project: tigon
81
+ rubygems_version: 1.6.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: A simple dsl for hash transformation.
85
+ test_files:
86
+ - spec/spec_helper.rb
87
+ - spec/unit/hash_transformer_spec.rb