helix 0.0.0.pre

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.
@@ -0,0 +1,145 @@
1
+ require 'helix/base'
2
+
3
+ module Helix
4
+
5
+ module Statistics
6
+
7
+ unless defined?(self::STORAGE_ACTION_FOR)
8
+ STORAGE_ACTION_FOR = {
9
+ track: "track_ingest/disk_usage",
10
+ image: "image_ingest/disk_usage",
11
+ video: "video_publish/disk_usage",
12
+ }
13
+ end
14
+
15
+ # @example
16
+ # Helix::Statistics.album_delivery #=> Array of Hashes of stats data
17
+ #
18
+ # @return [Array of Hashes] Statistics information.
19
+ def self.album_delivery(opts={})
20
+ self.image_delivery(opts)
21
+ end
22
+
23
+ # @example
24
+ # Helix::Statistics.album_storage #=> Array of Hashes of stats data
25
+ #
26
+ # @return [Array of Hashes] Statistics information.
27
+ def self.album_storage(opts={})
28
+ self.image_storage(opts)
29
+ end
30
+
31
+ # @example
32
+ # Helix::Statistics.audio_delivery #=> Array of Hashes of stats data
33
+ #
34
+ # @return [Array of Hashes] Statistics information.
35
+ def self.audio_delivery(opts={})
36
+ self.delivery(:track, opts)
37
+ end
38
+
39
+ # @example
40
+ # Helix::Statistics.audio_ingest #=> Array of Hashes of stats data
41
+ #
42
+ # @return [Array of Hashes] Statistics information.
43
+ def self.audio_ingest(opts={})
44
+ end
45
+
46
+ # @example
47
+ # Helix::Statistics.audio_storage #=> Array of Hashes of stats data
48
+ #
49
+ # @return [Array of Hashes] Statistics information.
50
+ def self.audio_storage(opts={})
51
+ self.storage(:track, opts)
52
+ end
53
+
54
+ # @example
55
+ # Helix::Statistics.image_delivery #=> Array of Hashes of stats data
56
+ #
57
+ # @return [Array of Hashes] Statistics information.
58
+ def self.image_delivery(opts={})
59
+ self.delivery(:image, opts)
60
+ end
61
+
62
+ # @example
63
+ # Helix::Statistics.image_storage #=> Array of Hashes of stats data
64
+ #
65
+ # @return [Array of Hashes] Statistics information.
66
+ def self.image_storage(opts={})
67
+ self.storage(:image, opts)
68
+ end
69
+
70
+ # @example
71
+ # Helix::Statistics.track_delivery #=> Array of Hashes of stats data
72
+ #
73
+ # @return [Array of Hashes] Statistics information.
74
+ def self.track_delivery(opts={})
75
+ self.audio_delivery(opts)
76
+ end
77
+
78
+ # @example
79
+ # Helix::Statistics.track_ingest #=> Array of Hashes of stats data
80
+ #
81
+ # @return [Array of Hashes] Statistics information.
82
+ def self.track_ingest(opts={})
83
+ self.audio_ingest(opts)
84
+ end
85
+
86
+ # @example
87
+ # Helix::Statistics.track_storage #=> Array of Hashes of stats data
88
+ #
89
+ # @return [Array of Hashes] Statistics information.
90
+ def self.track_storage(opts={})
91
+ self.audio_storage(opts)
92
+ end
93
+
94
+ # @example
95
+ # Helix::Statistics.video_delivery #=> Array of Hashes of stats data
96
+ #
97
+ # @return [Array of Hashes] Statistics information.
98
+ def self.video_delivery(opts={})
99
+ self.delivery(:video, opts)
100
+ end
101
+
102
+ # @example
103
+ # Helix::Statistics.video_ingest #=> Array of Hashes of stats data
104
+ #
105
+ # @return [Array of Hashes] Statistics information.
106
+ def self.video_ingest(opts={})
107
+ # encode, source, or breakdown
108
+ end
109
+
110
+ # @example
111
+ # Helix::Statistics.video_storage #=> Array of Hashes of stats data
112
+ #
113
+ # @return [Array of Hashes] Statistics information.
114
+ def self.video_storage(opts={})
115
+ self.storage(:video, opts)
116
+ end
117
+
118
+ private
119
+
120
+ def self.delivery(media_type, opts)
121
+ memo_cfg = Helix::Config.instance
122
+ guid = opts.delete("#{media_type}_id".to_sym)
123
+ url_opts = guid ?
124
+ {guid: guid, media_type: "#{media_type}s".to_sym, action: :statistics} :
125
+ {media_type: :statistics, action: "#{media_type}_delivery".to_sym}
126
+ url = memo_cfg.build_url(url_opts)
127
+ # We allow opts[:sig_type] for internal negative testing only.
128
+ memo_cfg.get_response(url, {sig_type: :view}.merge(opts))
129
+ end
130
+
131
+ def self.storage(media_type, opts)
132
+ memo_cfg = Helix::Config.instance
133
+ url_opts = {media_type: :statistics, action: storage_action_for(media_type)}
134
+ url = memo_cfg.build_url(url_opts)
135
+ # We allow opts[:sig_type] for internal negative testing only.
136
+ memo_cfg.get_response(url, {sig_type: :view}.merge(opts))
137
+ end
138
+
139
+ def self.storage_action_for(media_type)
140
+ STORAGE_ACTION_FOR[media_type].to_sym
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,17 @@
1
+ module Helix
2
+
3
+ class Track < Base
4
+
5
+ # The class name, to be used by supporting classes. Such as Config which uses
6
+ # this method as a way to build URLs.
7
+ #
8
+ #
9
+ # @example
10
+ # Helix::Track.media_type_sym #=> :track
11
+ #
12
+ # @return [Symbol] Name of the class.
13
+ def self.media_type_sym; :track; end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,19 @@
1
+ require 'helix/base'
2
+
3
+ module Helix
4
+
5
+ class Video < Base
6
+
7
+ # The class name, to be used by supporting classes. Such as Config which uses
8
+ # this method as a way to build URLs.
9
+ #
10
+ #
11
+ # @example
12
+ # Helix::Video.media_type_sym #=> :video
13
+ #
14
+ # @return [Symbol] Name of the class.
15
+ def self.media_type_sym; :video; end
16
+
17
+ end
18
+
19
+ end
data/lib/helix.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'helix/video'
2
+ require 'helix/track'
3
+ require 'helix/album'
4
+ require 'helix/image'
5
+ require 'helix/config'
6
+ require 'helix/statistics'
7
+
8
+ module Helix
9
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'helix'
3
+
4
+ describe Helix::Album do
5
+ let(:klass) { Helix::Album }
6
+
7
+ subject { klass }
8
+ its(:ancestors) { should include(Helix::Base) }
9
+ its(:guid_name) { should eq('album_id') }
10
+ its(:media_type_sym) { should be(:album) }
11
+ its(:plural_media_type) { should eq('albums') }
12
+
13
+ describe "Constants"
14
+
15
+ describe "an instance" do
16
+ let(:obj) { klass.new({'album_id' => 'some_album_guid'}) }
17
+ subject { obj }
18
+ its(:media_type_sym) { should be(:album) }
19
+ describe "#update" do
20
+ let(:meth) { :update }
21
+ it "should raise an error" do
22
+ expect(lambda { obj.send(meth) }).to raise_error("Albums Update is not currently supported.")
23
+ end
24
+ end
25
+ end
26
+
27
+ end
data/spec/base_spec.rb ADDED
@@ -0,0 +1,325 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'helix'
3
+
4
+ describe Helix::Base do
5
+
6
+ def set_stubs(obj, even_sig=false)
7
+ obj.instance_variable_set(:@attributes, {})
8
+ obj.stub(:media_type_sym) { :video }
9
+ obj.stub(:plural_media_type) { 'videos' }
10
+ obj.stub(:guid) { 'some_guid' }
11
+ obj.stub(:signature) { 'some_sig' } if even_sig
12
+ end
13
+
14
+ let(:klass) { Helix::Base }
15
+
16
+ subject { klass }
17
+
18
+ describe "Constants" do
19
+ describe "METHODS_DELEGATED_TO_CLASS" do
20
+ subject { klass::METHODS_DELEGATED_TO_CLASS }
21
+ it { should eq([:guid_name, :media_type_sym, :plural_media_type]) }
22
+ end
23
+ end
24
+
25
+ ### CLASS METHODS
26
+
27
+ describe ".create" do
28
+ let(:meth) { :create }
29
+ let(:mock_config) { mock(Helix::Config) }
30
+ subject { klass.method(meth) }
31
+ its(:arity) { should eq(-1) }
32
+ let(:klass_sym) { :klass }
33
+ let(:resp_value) { { klass_sym.to_s => { attribute: :value } } }
34
+ let(:resp_json) { "JSON" }
35
+ let(:params) { { signature: "some_sig" } }
36
+ let(:expected) { { attributes: { attribute: :value }, config: mock_config } }
37
+ before(:each) do
38
+ klass.stub(:plural_media_type) { :klasses }
39
+ klass.stub(:media_type_sym) { klass_sym }
40
+ mock_config.stub(:build_url).with(action: :create_many, media_type: :klasses) { :url }
41
+ mock_config.stub(:signature).with(:update) { "some_sig" }
42
+ Helix::Config.stub(:instance) { mock_config }
43
+ end
44
+ it "should get an ingest signature" do
45
+ mock_config.should_receive(:build_url).with(media_type: :klasses,
46
+ format: :xml)
47
+ RestClient.stub(:post).with(:url, params) { resp_json }
48
+ Crack::XML.should_receive(:parse).with(resp_json) { resp_value }
49
+ klass.stub(:new).with(expected)
50
+ mock_config.should_receive(:signature).with(:update) { "some_sig" }
51
+ klass.send(meth)
52
+ end
53
+ it "should do an HTTP post call, parse response and call new" do
54
+ mock_config.should_receive(:build_url).with(media_type: :klasses,
55
+ format: :xml)
56
+ RestClient.should_receive(:post).with(:url, params) { resp_json }
57
+ Crack::XML.should_receive(:parse).with(resp_json) { resp_value }
58
+ klass.should_receive(:new).with(expected)
59
+ klass.send(meth)
60
+ end
61
+ end
62
+
63
+ describe ".find" do
64
+ let(:meth) { :find }
65
+ let(:mock_config) { mock(Helix::Config) }
66
+ let(:mock_obj) { mock(klass, :load => :output_of_load) }
67
+ subject { klass.method(meth) }
68
+ its(:arity) { should eq(1) }
69
+ before(:each) do Helix::Config.stub(:instance) { mock_config } end
70
+ context "when given a Helix::Config instance and a guid" do
71
+ let(:guid) { :a_guid }
72
+ let(:guid_name) { :the_guid_name }
73
+ let(:mock_attrs) { mock(Object, :[]= => :output_of_setting_val) }
74
+ before(:each) do
75
+ klass.stub(:attributes) { mock_attrs }
76
+ klass.stub(:guid_name) { guid_name }
77
+ klass.stub(:new) { mock_obj }
78
+ end
79
+ it "should instantiate with {attributes: guid_name => the_guid, config: config}" do
80
+ klass.should_receive(:new).with({attributes: {guid_name => guid}, config: mock_config})
81
+ klass.send(meth, guid)
82
+ end
83
+ it "should load" do
84
+ mock_obj.should_receive(:load)
85
+ klass.send(meth, guid)
86
+ end
87
+ end
88
+ end
89
+
90
+ describe ".find_all" do
91
+ let(:meth) { :find_all }
92
+ let(:mock_config) { mock(Helix::Config, build_url: :built_url, get_response: {}) }
93
+ subject { klass.method(meth) }
94
+ its(:arity) { should eq(1) }
95
+ before(:each) do Helix::Config.stub(:instance) { mock_config } end
96
+ context "when given a config instances and an opts Hash" do
97
+ let(:opts) { {opts_key1: :opts_val1} }
98
+ let(:plural_media_type) { :videos }
99
+ before(:each) do klass.stub(:plural_media_type) { plural_media_type } end
100
+ it "should build a JSON URL -> the_url" do
101
+ mock_config.should_receive(:build_url).with(format: :json)
102
+ klass.send(meth, opts)
103
+ end
104
+ it "should get_response(the_url, {sig_type: :view}.merge(opts) -> raw_response" do
105
+ mock_config.should_receive(:get_response).with(:built_url, {sig_type: :view}.merge(opts))
106
+ klass.send(meth, opts)
107
+ end
108
+ it "should read raw_response[plural_media_type] -> data_sets" do
109
+ mock_raw_response = mock(Object)
110
+ mock_config.stub(:get_response) { mock_raw_response }
111
+ mock_raw_response.should_receive(:[]).with(plural_media_type)
112
+ klass.send(meth, opts)
113
+ end
114
+ context "when data_sets is nil" do
115
+ it "should return []" do expect(klass.send(meth, opts)).to eq([]) end
116
+ end
117
+ context "when data_sets is NOT nil" do
118
+ let(:data_set) { (0..2).to_a }
119
+ before(:each) do mock_config.stub(:get_response) { {plural_media_type => data_set } } end
120
+ it "should map instantiation with attributes: each data set element" do
121
+ klass.should_receive(:new).with(attributes: data_set[0]) { :a }
122
+ klass.should_receive(:new).with(attributes: data_set[1]) { :b }
123
+ klass.should_receive(:new).with(attributes: data_set[2]) { :c }
124
+ expect(klass.send(meth, opts)).to eq([:a, :b, :c])
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "an instance" do
131
+ let(:obj) { klass.new({}) }
132
+
133
+ ### INSTANCE METHODS
134
+
135
+ describe "#destroy" do
136
+ let(:meth) { :destroy }
137
+ let(:mock_config) { mock(Helix::Config, build_url: :the_built_url, signature: :some_sig) }
138
+ subject { obj.method(meth) }
139
+ let(:params) { { params: {signature: :some_sig } } }
140
+ before do
141
+ obj.stub(:config) { mock_config }
142
+ obj.stub(:guid) { :some_guid }
143
+ obj.stub(:plural_media_type) { :media_type }
144
+ end
145
+ it "should get an update signature" do
146
+ url = mock_config.build_url(media_type: :media_type,
147
+ guid: :some_guid,
148
+ format: :xml)
149
+ RestClient.stub(:delete).with(url, params)
150
+ mock_config.should_receive(:signature).with(:update) { :some_sig }
151
+ obj.send(meth)
152
+ end
153
+ it "should call for an HTTP delete and return nil" do
154
+ url = mock_config.build_url(media_type: :media_type,
155
+ guid: :some_guid,
156
+ format: :xml)
157
+ RestClient.should_receive(:delete).with(url, params)
158
+ expect(obj.send(meth)).to be_nil
159
+ end
160
+ end
161
+
162
+ describe "#guid" do
163
+ let(:meth) { :guid }
164
+ it "should return @attributes[guid_name]" do
165
+ mock_attributes = mock(Object)
166
+ obj.instance_variable_set(:@attributes, mock_attributes)
167
+ obj.should_receive(:guid_name) { :the_guid_name }
168
+ mock_attributes.should_receive(:[]).with(:the_guid_name) { :expected }
169
+ expect(obj.send(meth)).to eq(:expected)
170
+ end
171
+ end
172
+
173
+ describe "#guid_name" do
174
+ let(:meth) { :guid_name }
175
+ it "should delegate to the class" do
176
+ klass.should_receive(meth) { :expected }
177
+ expect(obj.send(meth)).to be(:expected)
178
+ end
179
+ end
180
+
181
+ describe "#load" do
182
+ let(:meth) { :load }
183
+ let(:mock_config) { mock(Helix::Config) }
184
+ subject { obj.method(meth) }
185
+ its(:arity) { should eq(-1) }
186
+ before(:each) do
187
+ obj.stub(:config) { mock_config }
188
+ obj.stub(:guid) { 'some_guid' }
189
+ obj.stub(:signature) { 'some_sig' }
190
+ obj.stub(:massage_raw_attrs) { :massaged_attrs }
191
+ mock_config.stub(:build_url) { :expected_url }
192
+ mock_config.stub(:get_response) { :raw_attrs }
193
+ klass.stub(:media_type_sym) { :video }
194
+ end
195
+ shared_examples_for "builds URL for load" do
196
+ it "should call #guid" do
197
+ obj.should_receive(:guid) { 'some_guid' }
198
+ obj.send(meth)
199
+ end
200
+ it "should build_url(format: :json, guid: the_guid, media_type: 'videos')" do
201
+ mock_config.should_receive(:build_url).with(format: :json, guid: 'some_guid', media_type: 'videos')
202
+ RestClient.stub(:put)
203
+ obj.send(meth)
204
+ end
205
+ end
206
+ context "when given no argument" do
207
+ it_behaves_like "builds URL for load"
208
+ it "should call klass.get_response(output_of_build_url, {sig_type: :view}) and return instance of klass" do
209
+ mock_config.should_receive(:get_response).with(:expected_url, {sig_type: :view})
210
+ expect(obj.send(meth)).to be_an_instance_of(klass)
211
+ end
212
+ it "should massage the raw_attrs" do
213
+ obj.should_receive(:massage_raw_attrs).with(:raw_attrs)
214
+ obj.send(meth)
215
+ end
216
+ end
217
+ context "when given an opts argument of {key1: :value1}" do
218
+ let(:opts) { {key1: :value1} }
219
+ it_behaves_like "builds URL for load"
220
+ it "should call klass.get_response(output_of_build_url, opts.merge(sig_type: :view)) and return instance of klass" do
221
+ mock_config.should_receive(:get_response).with(:expected_url, opts.merge(sig_type: :view))
222
+ expect(obj.send(meth, opts)).to be_an_instance_of(klass)
223
+ end
224
+ it "should massage the raw_attrs" do
225
+ obj.should_receive(:massage_raw_attrs).with(:raw_attrs)
226
+ obj.send(meth, opts)
227
+ end
228
+ end
229
+ end
230
+
231
+ describe "#massage_raw_attrs" do
232
+ let(:meth) { :massage_raw_attrs }
233
+ let(:guid_name) { :the_guid_name }
234
+
235
+ subject { obj.method(meth) }
236
+ its(:arity) { should eq(1) }
237
+
238
+ before(:each) { obj.stub(:guid_name) { guid_name } }
239
+ context "when given {}" do
240
+ let(:raw_attrs) { {} }
241
+ subject { obj.send(meth, raw_attrs) }
242
+ it { should eq(nil) }
243
+ end
244
+ context "when given { guid_name => :the_val }" do
245
+ let(:raw_attrs) { { guid_name => :the_val } }
246
+ subject { obj.send(meth, raw_attrs) }
247
+ it { should eq(raw_attrs) }
248
+ end
249
+ context "when given [{ guid_name => :the_val }]" do
250
+ let(:raw_attrs) { [{ guid_name => :the_val }] }
251
+ subject { obj.send(meth, raw_attrs) }
252
+ it { should eq(raw_attrs.first) }
253
+ end
254
+ end
255
+
256
+ describe "#method_missing" do
257
+ let(:meth) { :method_missing }
258
+ subject { obj.method(meth) }
259
+ its(:arity) { should eq(1) }
260
+ context "when given method_sym" do
261
+ let(:method_sym) { :method_sym }
262
+ let(:mock_attributes) { mock(Object) }
263
+ before(:each) do obj.instance_variable_set(:@attributes, mock_attributes) end
264
+ context "and @attributes[method_sym.to_s] raises an exception" do
265
+ before(:each) do mock_attributes.should_receive(:[]).with(method_sym.to_s).and_raise("some exception") end
266
+ it "should raise a NoMethodError" do
267
+ msg = "#{method_sym} is not recognized within #{klass}'s @attributes"
268
+ expect(lambda { obj.send(meth, method_sym) }).to raise_error(msg)
269
+ end
270
+ end
271
+ context "and @attributes[method_sym.to_s] does NOT raise an exception" do
272
+ before(:each) do mock_attributes.should_receive(:[]).with(method_sym.to_s) { :expected } end
273
+ it "should return @attributes[method_sym.to_s]" do
274
+ expect(obj.send(meth, method_sym)).to eq(:expected)
275
+ end
276
+ end
277
+ end
278
+ end
279
+
280
+ describe "#update" do
281
+ let(:meth) { :update }
282
+ let(:mock_config) { mock(Helix::Config) }
283
+ subject { obj.method(meth) }
284
+ its(:arity) { should eq(-1) }
285
+ before(:each) do
286
+ obj.stub(:config) { mock_config }
287
+ obj.stub(:guid) { :the_guid }
288
+ obj.stub(:media_type_sym) { :video }
289
+ obj.stub(:plural_media_type) { :the_media_type }
290
+ mock_config.stub(:signature).with(:update) { 'some_sig' }
291
+ mock_config.stub(:build_url) { :expected_url }
292
+ end
293
+ shared_examples_for "builds URL for update" do
294
+ it "should build_url(format: :xml, guid: guid, media_type: plural_media_type)" do
295
+ mock_config.should_receive(:build_url).with(format: :xml, guid: :the_guid, media_type: :the_media_type)
296
+ RestClient.stub(:put)
297
+ obj.send(meth)
298
+ end
299
+ it "should get an update signature" do
300
+ mock_config.stub(:build_url)
301
+ RestClient.stub(:put)
302
+ mock_config.should_receive(:signature).with(:update) { 'some_sig' }
303
+ obj.send(meth)
304
+ end
305
+ end
306
+ context "when given no argument" do
307
+ it_behaves_like "builds URL for update"
308
+ it "should call RestClient.put(output_of_build_url, {signature: the_sig, video: {}}) and return instance of klass" do
309
+ RestClient.should_receive(:put).with(:expected_url, {signature: 'some_sig', video: {}})
310
+ expect(obj.send(meth)).to be_an_instance_of(klass)
311
+ end
312
+ end
313
+ context "when given an opts argument of {key1: :value1}" do
314
+ let(:opts) { {key1: :value1} }
315
+ it_behaves_like "builds URL for update"
316
+ it "should call RestClient.put(output_of_build_url, {signature: the_sig, video: opts}) and return instance of klass" do
317
+ RestClient.should_receive(:put).with(:expected_url, {signature: 'some_sig', video: opts})
318
+ expect(obj.send(meth, opts)).to be_an_instance_of(klass)
319
+ end
320
+ end
321
+ end
322
+
323
+ end
324
+
325
+ end