spigot 0.1.0 → 0.2.0

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +25 -32
  4. data/Rakefile +6 -0
  5. data/examples/active_record.rb +18 -15
  6. data/examples/model.rb +38 -7
  7. data/lib/spigot.rb +18 -6
  8. data/lib/spigot/configuration.rb +4 -5
  9. data/lib/spigot/map/base.rb +44 -0
  10. data/lib/spigot/map/definition.rb +69 -0
  11. data/lib/spigot/map/option.rb +27 -0
  12. data/lib/spigot/map/resource.rb +37 -0
  13. data/lib/spigot/map/service.rb +43 -0
  14. data/lib/spigot/patch.rb +1 -1
  15. data/lib/spigot/proxy.rb +3 -2
  16. data/lib/spigot/translator.rb +22 -71
  17. data/lib/spigot/version.rb +1 -1
  18. data/script/console.rb +26 -20
  19. data/spec/fixtures/data/active_user.rb +17 -0
  20. data/spec/fixtures/data/post.rb +15 -0
  21. data/spec/fixtures/data/user.rb +41 -0
  22. data/spec/fixtures/mappings/active_user_map.rb +58 -22
  23. data/spec/fixtures/mappings/post_map.rb +10 -10
  24. data/spec/fixtures/mappings/user_map.rb +73 -29
  25. data/spec/spec_helper.rb +3 -12
  26. data/spec/spigot/active_record_spec.rb +34 -26
  27. data/spec/spigot/base_spec.rb +32 -1
  28. data/spec/spigot/configuration_spec.rb +0 -27
  29. data/spec/spigot/map/base_spec.rb +70 -0
  30. data/spec/spigot/map/definition_spec.rb +45 -0
  31. data/spec/spigot/map/resource_spec.rb +57 -0
  32. data/spec/spigot/map/service_spec.rb +88 -0
  33. data/spec/spigot/translator_spec.rb +110 -113
  34. data/spigot.gemspec +3 -2
  35. metadata +43 -20
  36. data/examples/.DS_Store +0 -0
  37. data/lib/.DS_Store +0 -0
  38. data/lib/spigot/config/.DS_Store +0 -0
  39. data/spec/.DS_Store +0 -0
  40. data/spec/fixtures/.DS_Store +0 -0
  41. data/spec/fixtures/api_data.rb +0 -46
  42. data/spec/spigot/factory_spec.rb +0 -5
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spigot::Map::Definition do
4
+ let(:resource){Spigot::Map::Resource.new(:user)}
5
+
6
+ context '#initialize' do
7
+ it 'assigns variables' do
8
+ subject = Spigot::Map::Definition.new(:foo, 'bar')
9
+ subject.instance_variable_get(:@name).should_not be_nil
10
+ subject.instance_variable_get(:@value).should_not be_nil
11
+ end
12
+
13
+ context '#with a block' do
14
+ it 'assigns parse' do
15
+ subject = Spigot::Map::Definition.new(:foo, 'bar'){'baz'}
16
+ subject.instance_variable_get(:@parse).should_not be_nil
17
+ end
18
+ end
19
+ end
20
+
21
+ context '#define' do
22
+
23
+ it 'returns a definition with the given key and value' do
24
+ subject = Spigot::Map::Definition.define(resource, :foo, 'bar')
25
+ subject.instance_variable_get(:@name).should eq(:foo)
26
+ subject.instance_variable_get(:@value).should eq('bar')
27
+ end
28
+
29
+ it 'accepts a block of definitions' do
30
+ subject = Spigot::Map::Definition.define(resource, :foo) do
31
+ bar :baz
32
+ qux :mjw
33
+ end
34
+ subject.instance_variable_get(:@parse).should be_nil
35
+ subject.instance_variable_get(:@children).length.should eq(2)
36
+ end
37
+
38
+ it 'assigns a parse block' do
39
+ subject = Spigot::Map::Definition.define(resource, :foo){|val| "formatted-#{val}" }
40
+ subject.instance_variable_get(:@parse).should_not be_nil
41
+ subject.instance_variable_get(:@children).length.should eq(0)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spigot::Map::Resource do
4
+ let(:subject){Spigot::Map::Resource.new(:user){ username :login }}
5
+
6
+ context '#initialize' do
7
+ it 'assigns a name' do
8
+ subject.instance_variable_get(:@name).should eq(:user)
9
+ end
10
+
11
+ it 'does not require a block' do
12
+ expect{
13
+ Spigot::Map::Resource.new(:user)
14
+ }.to_not raise_error(ArgumentError)
15
+ end
16
+
17
+ it 'builds definitions included in block' do
18
+ Spigot::Map::Definition.should_receive(:define)
19
+ subject #=> Evaluate the let statement
20
+ end
21
+ end
22
+
23
+ context '#method_missing' do
24
+ before do
25
+ subject
26
+ Spigot::Map::Definition.should_receive(:define)
27
+ end
28
+
29
+ it 'builds a definition for missing methods' do
30
+ subject.username :login
31
+ end
32
+
33
+ it 'allows for assignment' do
34
+ subject.username = :login
35
+ end
36
+ end
37
+
38
+ context '.options' do
39
+ let(:subject){Spigot::Map::Resource.new(:user){ options{ primary_key :foo } }}
40
+
41
+ it 'sets the options' do
42
+ options = subject.instance_variable_get(:@options)
43
+ options.primary_key.should eq(:foo)
44
+ end
45
+ end
46
+
47
+ context '.to_hash' do
48
+ it 'returns a hash of resources' do
49
+ subject.to_hash.should be_a_kind_of(Hash)
50
+ end
51
+
52
+ it 'returns the resource values' do
53
+ subject.to_hash[:user][:username].should eq(:login)
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spigot::Map::Service do
4
+ let(:klass){ Spigot::Map::Service }
5
+ let(:subject){ klass.new(:github) }
6
+
7
+ before{ Spigot::Map::Base.new }
8
+
9
+ context '#initialize' do
10
+ it 'assigns a name' do
11
+ subject.name.should eq(:github)
12
+ end
13
+
14
+ it 'initializes an empty array of resources' do
15
+ subject.resources.should eq([])
16
+ end
17
+ end
18
+
19
+ context '#service' do
20
+ it 'works with a block' do
21
+ Spigot::Map::Service.should_receive(:new).with(:github)
22
+
23
+ klass.service(:github){'foo'}
24
+ end
25
+
26
+ it 'works without a block' do
27
+ Spigot::Map::Service.should_receive(:new).with(:github)
28
+ expect{
29
+ klass.service(:github)
30
+ }.to_not raise_error(ArgumentError)
31
+ end
32
+
33
+ it 'adds the created service to the current map' do
34
+ Spigot.config.map.should_receive(:update)
35
+ klass.service(:github)
36
+ end
37
+
38
+ context 'duplicate services' do
39
+ let(:service){Spigot::Map::Service.new(:github)}
40
+ before do
41
+ Spigot.config.map.update(:github, service)
42
+ end
43
+
44
+ it 'uses an existing service if already defined' do
45
+ service.should_receive(:instance_eval)
46
+ Spigot.config.map.should_receive(:update).with(:github, service)
47
+ klass.service(:github){'foo'}
48
+ end
49
+
50
+ it 'does not duplicate services' do
51
+ klass.service(:github)
52
+ Spigot.config.map.services.length.should eq(1)
53
+ end
54
+ end
55
+ end
56
+
57
+ context '.resource' do
58
+ it 'builds a resource' do
59
+ Spigot::Map::Resource.should_receive(:new).with(:user)
60
+ subject.resource(:user){'foo'}
61
+ end
62
+
63
+ it 'does not require a block' do
64
+ expect{
65
+ subject.resource(:user)
66
+ }.to_not raise_error(ArgumentError)
67
+ end
68
+ end
69
+
70
+ context '.reset' do
71
+ it 'resets the resources' do
72
+ subject.resource(:user)
73
+ expect{
74
+ subject.reset
75
+ }.to change{subject.resources.length}.by(-1)
76
+ end
77
+ end
78
+
79
+ context '.[]' do
80
+ it 'returns the resource by name' do
81
+ subject.resource(:user)
82
+ user = subject[:user]
83
+ user.should be_a_kind_of(Spigot::Map::Resource)
84
+ user.instance_variable_get(:@name).should eq(:user)
85
+ end
86
+ end
87
+
88
+ end
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Spigot::Translator do
4
-
5
4
  context '#initialize' do
5
+ before{ Spigot::Mapping::User.basic }
6
6
  it 'requires a service' do
7
7
  expect{
8
8
  Spigot::Translator.new(nil, Struct)
@@ -22,22 +22,18 @@ describe Spigot::Translator do
22
22
  end
23
23
  end
24
24
 
25
- context '#format' do
26
- let(:subject){Spigot::Translator.new(:github, User.new, {a: '1'})}
27
-
28
- context 'with a missing map' do
29
- it 'raises error with a missing file' do
30
- expect {
31
- subject.format
32
- }.to raise_error(Spigot::MissingServiceError)
33
- end
25
+ context '.id' do
26
+ let(:subject){ Spigot::Translator.new(:github, User.new, Spigot::Data::User.basic) }
27
+ before{ Spigot::Mapping::User.basic }
28
+ it 'returns the value at the foreign_key' do
29
+ subject.stubs(:foreign_key).returns('id')
30
+ subject.id.should eq('123')
34
31
  end
32
+ end
35
33
 
34
+ context '.format' do
36
35
  context 'with a missing resource map' do
37
- before do
38
- subject.stubs(:translation_file).returns("missing:\n foo: 'bar'")
39
- end
40
-
36
+ let(:subject){ Spigot::Translator.new(:github, User.new, Spigot::Data::User.basic) }
41
37
  it 'raises error with a missing resource map' do
42
38
  expect{
43
39
  subject.format
@@ -45,86 +41,106 @@ describe Spigot::Translator do
45
41
  end
46
42
  end
47
43
 
48
- context 'with a symbol keyed map' do
49
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.basic_user)}
50
-
51
- context 'with a basic mapping' do
52
- with_mapping(:basic_user, Spigot::Mapping::User.symbolized)
44
+ context 'with a valid resource map' do
45
+ context 'with a simple map' do
46
+ let(:data){ Spigot::Data::User.basic }
47
+ let(:subject){ Spigot::Translator.new(:github, User.new, data) }
48
+ before{ Spigot::Mapping::User.basic }
49
+ it 'returns empty hash from nil data' do
50
+ subject.data = {}
51
+ expect(subject.format).to eq({name: nil, username: nil})
52
+ end
53
53
 
54
54
  it 'reads one layer' do
55
- expect(subject.format).to eq({'name' => 'Dean Martin', 'username' => 'classyasfuck'})
55
+ expect(subject.format).to eq({name: 'Dean Martin', username: 'classyasfuck'})
56
56
  end
57
57
  end
58
- end
59
-
60
- context 'and a valid resource map' do
61
- with_mapping(:basic_user, Spigot::Mapping::User.basic)
62
-
63
- it 'returns empty hash from nil data' do
64
- expect(subject.format).to eq({})
65
- end
66
- end
67
58
 
68
- context 'with basic user data' do
69
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.basic_user)}
59
+ context 'with a nested map' do
60
+ let(:data){ Spigot::Data::User.nested }
61
+ let(:subject){ Spigot::Translator.new(:github, User.new, data) }
62
+ before{ Spigot::Mapping::User.nested }
70
63
 
71
- context 'with a basic mapping' do
72
- with_mapping(:basic_user, Spigot::Mapping::User.basic)
73
-
74
- it 'reads one layer' do
75
- expect(subject.format).to eq({'name' => 'Dean Martin', 'username' => 'classyasfuck'})
64
+ it 'traverses into the nested hash' do
65
+ expect(subject.format).to eq({
66
+ name: 'Dean Martin',
67
+ username: 'classyasfuck',
68
+ contact: 'dino@amore.io'
69
+ })
76
70
  end
77
71
  end
78
72
 
79
- context 'with a mapping containing nested data' do
80
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.nested_user)}
81
- with_mapping(:basic_user, Spigot::Mapping::User.nested)
73
+ context "nested twice" do
74
+ let(:data){Spigot::Data::User.double_nested}
75
+ let(:subject){Spigot::Translator.new(:github, User.new, data)}
76
+ before{ Spigot::Mapping::User.nested_twice }
82
77
 
83
- it 'traverses into the nested hash' do
78
+ it 'traverses multiple levels' do
84
79
  expect(subject.format).to eq({
85
- 'name' => 'Dean Martin',
86
- 'username' => 'classyasfuck',
87
- 'contact' => 'dino@amore.io'
80
+ name: 'Dean Martin',
81
+ ip: "127.0.0.1",
82
+ username: 'classyasfuck',
83
+ contact: 'dino@amore.io'
88
84
  })
89
85
  end
86
+ end
90
87
 
91
- context 'twice' do
92
- with_mapping(:basic_user, Spigot::Mapping::User.nested_twice)
93
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.double_nested_user)}
88
+ context 'with an array of values' do
89
+ let(:data){Spigot::Data::User.array}
90
+ let(:subject){Spigot::Translator.new(:github, User.new, data)}
91
+ before{ Spigot::Mapping::User.basic }
94
92
 
95
- it 'traverses multiple levels' do
96
- expect(subject.format.values).to include(*['Dean Martin','classyasfuck','dino@amore.io'])
97
- end
93
+ it 'returns an array of formatted data' do
94
+ subject.format.should eq([
95
+ {name: "Dean Martin", username: "classyasfuck"},
96
+ {name: "Frank Sinatra", username: "livetilidie"}
97
+ ])
98
98
  end
99
99
  end
100
- end
101
100
 
102
- context 'with an array of values' do
103
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.user_array)}
104
- with_mapping(:basic_user, Spigot::Mapping::User.basic)
101
+ context 'with a nested array of values' do
102
+ let(:data){ Spigot::Data::User.nested_array }
103
+ let(:subject){Spigot::Translator.new(:github, User.new, data)}
104
+ before{ Spigot::Mapping::User.nested_array }
105
105
 
106
- it 'returns an array of formatted data' do
107
- expect(subject.format.length).to eq(2)
108
- expect(subject.format.map{|u| u['name']}).to include('Dean Martin', 'Frank Sinatra')
106
+ it 'handles a nested array of values' do
107
+ subject.format.should eq({
108
+ name: 'Rockafella',
109
+ user_count: 2,
110
+ users: [{name: "Dean Martin", username: "classyasfuck"}, {name: "Frank Sinatra", username: "livetilidie"}]
111
+ })
112
+ end
109
113
  end
110
- end
111
114
 
112
- context 'with a nested array of values' do
113
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.nested_user_array)}
114
- with_mapping(:basic_user, Spigot::Mapping::User.nested_array)
115
+ context 'with a namedspaced resource' do
116
+ let(:data){ Spigot::Data::Post.basic }
117
+ let(:subject){Spigot::Translator.new(:github, Wrapper::Post.new, data)}
118
+ before{ Spigot::Mapping::Post.basic }
115
119
 
116
- it 'handles a nested array of values' do
117
- expect(subject.format.keys).to include('name', 'users', 'user_count')
118
- expect(subject.format['users']).to be_a(Array)
120
+ it 'accesses the wrapper/post key' do
121
+ subject.format.should eq({
122
+ title: 'Brief Article',
123
+ description: 'lorem ipsum'
124
+ })
125
+ end
119
126
  end
120
- end
121
127
 
122
- context 'with a namedspaced resource' do
123
- let(:subject){Spigot::Translator.new(:github, Wrapper::Post.new, Spigot::ApiData.post)}
124
- with_mapping(:namespaced_post, Spigot::Mapping::Post.namespaced)
128
+ context 'with an interpolated value' do
129
+ let(:data){ Spigot::Data::User.basic }
130
+ let(:subject){ Spigot::Translator.new(:github, User.new, data) }
131
+ before{ Spigot::Mapping::User.interpolated }
132
+ it 'reads one layer' do
133
+ expect(subject.format).to eq({name: 'Dean Martin', username: '@classyasfuck'})
134
+ end
135
+ end
125
136
 
126
- it 'accesses the wrapper/post key' do
127
- expect(subject.format).to eq({'title' => 'Regular Article', 'description' => 'dolor sit amet'})
137
+ context 'with a nested interpolated value' do
138
+ let(:data){ Spigot::Data::User.nested }
139
+ let(:subject){ Spigot::Translator.new(:github, User.new, data) }
140
+ before{ Spigot::Mapping::User.nested_interpolation }
141
+ it 'reads one layer' do
142
+ expect(subject.format).to eq({name: 'Dean Martin', contact: 'dino@amore.io', username: '@classyasfuck'})
143
+ end
128
144
  end
129
145
  end
130
146
  end
@@ -137,75 +153,56 @@ describe Spigot::Translator do
137
153
  end
138
154
  end
139
155
 
140
- context '#id' do
141
- let(:subject){Spigot::Translator.new(:github, User.new, {id: '123'})}
142
-
143
- it 'returns the value at the foreign_key' do
144
- subject.stubs(:foreign_key).returns('id')
145
- subject.id.should eq('123')
146
- end
147
- end
148
-
149
156
  context '#conditions' do
150
- let(:subject){Spigot::Translator.new(:github, User.new, Spigot::ApiData.user)}
151
- with_mapping(:user_with_conditions, Spigot::Mapping::User.with_options)
152
-
153
- it 'should return a hash' do
154
- previous_translations = Spigot.config.translations
155
- Spigot.configure{|c| c.translations = Spigot::Mapping::User.with_options }
156
- subject.conditions.should eq({"username"=>"classyasfuck"})
157
- Spigot.configure{|c| c.translations = previous_translations }
157
+ let(:data){ Spigot::Data::User.basic }
158
+ let(:subject){Spigot::Translator.new(:github, User.new, data)}
159
+
160
+ context 'without conditions specified' do
161
+ before{ Spigot::Mapping::User.basic }
162
+ it 'should return a hash' do
163
+ subject.conditions.should eq({'github_id' => nil})
164
+ end
158
165
  end
159
166
 
160
167
  context 'with conditions specified' do
161
- with_mapping(:user_with_conditions, Spigot::Mapping::User.with_conditions)
162
-
168
+ before{ Spigot::Mapping::User.with_conditions }
163
169
  it 'can specify the keys used in the map options' do
164
- subject.conditions.should eq({"username"=>"classyasfuck", "name"=>"Dean Martin"})
170
+ subject.conditions.should eq({username: "classyasfuck"})
165
171
  end
166
172
 
167
173
  it 'can specify only one key' do
168
- subject.conditions.should eq({"username"=>"classyasfuck", "name"=>"Dean Martin"})
174
+ subject.conditions.should eq({username: "classyasfuck"})
169
175
  end
170
176
  end
171
177
  end
172
178
 
173
179
  context '#options' do
174
- let(:subject){Spigot::Translator.new(:github, User.new, {remote_id: '987'})}
180
+ let(:subject){ Spigot::Translator.new(:github, User.new, {remote_id: '987'}) }
175
181
 
176
182
  context 'without options provided' do
177
- with_mapping(:basic_user, Spigot::Mapping::User.basic)
178
-
179
- context 'defaults' do
180
- it '#primary_key is the name of the service _id' do
181
- subject.primary_key.should eq('github_id')
182
- end
183
+ before{ Spigot::Mapping::User.basic }
184
+ it '#primary_key is the name of the service_id' do
185
+ subject.primary_key.should eq('github_id')
186
+ end
183
187
 
184
- it '#foreign_key is id' do
185
- subject.foreign_key.should eq('id')
186
- end
188
+ it '#foreign_key is id' do
189
+ subject.foreign_key.should eq('id')
187
190
  end
188
191
  end
189
192
 
190
193
  context 'with options provided' do
191
- with_mapping(:user_with_options, Spigot::Mapping::User.with_options)
192
-
193
- it 'reads the options from the spigot key' do
194
- subject.options.should eq(Spigot::Mapping::User.with_options['user']['spigot'])
194
+ before{ Spigot::Mapping::User.with_options }
195
+ it 'reads a primary key from the mapping' do
196
+ subject.primary_key.should eq(:username)
195
197
  end
196
198
 
197
- context '#primary_key' do
198
- it 'reads a primary key from the mapping' do
199
- subject.primary_key.should eq('username')
200
- end
199
+ it 'reads a foreign key from the mapping' do
200
+ subject.foreign_key.should eq(:login)
201
201
  end
202
202
 
203
- context '#foreign_key' do
204
- it 'reads a foreign key from the mapping' do
205
- subject.foreign_key.should eq('login')
206
- end
203
+ it 'reads options' do
204
+ subject.options.should be_a_kind_of(Spigot::Map::Option)
207
205
  end
208
206
  end
209
207
  end
210
-
211
208
  end