tigon 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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