spigot 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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