helix 0.0.4.3.pre → 0.0.4.4.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.
@@ -137,8 +137,8 @@ module Helix
137
137
  base_url_opts = {content_type: (opts[:content_type] || :json)}
138
138
  url = memo_cfg.build_url(base_url_opts.merge(guid: self.guid, resource_label: plural_resource_label))
139
139
  # We allow opts[:sig_type] for internal negative testing only.
140
- raw_attrs = memo_cfg.get_response(url, {sig_type: :view}.merge(opts))
141
- @attributes = massage_raw_attrs(raw_attrs)
140
+ raw_attrs = memo_cfg.get_response(url, {sig_type: :view}.merge(opts))
141
+ @attributes = massage_raw_attrs(raw_attrs)
142
142
  self
143
143
  end
144
144
  alias_method :reload, :load
@@ -166,6 +166,7 @@ module Helix
166
166
  private
167
167
 
168
168
  def massage_raw_attrs(raw_attrs)
169
+ return raw_attrs['site'] if raw_attrs.respond_to?(:has_key?) && raw_attrs.has_key?('site')
169
170
  # FIXME: Albums JSON output is embedded as the only member of an Array.
170
171
  proper_hash = raw_attrs.respond_to?(:has_key?) && raw_attrs.has_key?(guid_name)
171
172
  proper_hash ? raw_attrs : raw_attrs.first
@@ -0,0 +1,67 @@
1
+ module Helix
2
+
3
+ module BuildsUrls
4
+
5
+ unless defined?(self::SCOPES)
6
+ SCOPES = [:reseller, :company, :library]
7
+ end
8
+
9
+ # Creates additional URL stubbing that can be used in conjuction
10
+ # with the base_url to create RESTful URLs
11
+ #
12
+ # @param [String] base_url the base part of the URL to be used
13
+ # @param [Hash] opts a hash of options for building URL additions
14
+ # @return [String] The full RESTful URL string object
15
+ def add_sub_urls(base_url, opts)
16
+ guid, action, format = [:guid, :action, :formats].map { |sub| opts[sub] }
17
+ url = sub_url_scoping(base_url, opts)
18
+ url += "/#{guid}" if guid
19
+ url += "/formats/#{format}" if format
20
+ url += "/#{action}" if action
21
+ return url if opts[:content_type].blank?
22
+ "#{url}.#{opts[:content_type]}"
23
+ end
24
+
25
+ # Creates a full RESTful URL to be used for HTTP requests.
26
+ #
27
+ # @param [Hash] opts a hash of options for building URL
28
+ # @return [String] The full RESTful URL string object
29
+ def build_url(opts={})
30
+ opts[:content_type] ||= :xml
31
+ opts[:resource_label] ||= :videos
32
+ base_url = get_base_url(opts)
33
+ url = add_sub_urls(base_url, opts)
34
+ end
35
+
36
+ # Creates the base url with information collected from credentials.
37
+ #
38
+ # @param [Hash] opts a hash of options for building URL
39
+ # @return [String] The base RESTful URL string object
40
+ def get_base_url(opts)
41
+ creds = credentials
42
+ base_url = creds[:site]
43
+ return base_url if opts[:guid] || opts[:action] == :create_many
44
+ reseller, company, library = SCOPES.map { |scope| creds[scope] }
45
+ base_url += "/resellers/#{reseller}" if reseller
46
+ if company
47
+ base_url += "/companies/#{company}"
48
+ base_url += "/libraries/#{library}" if library
49
+ end
50
+ base_url
51
+ end
52
+
53
+ private
54
+
55
+ def sub_url_scoping(base_url, opts)
56
+ resource_label = opts[:resource_label]
57
+ if resource_label == 'libraries' and base_url !~ /companies/
58
+ co_id = opts[:company] || credentials[:company]
59
+ raise "No company to scope to: #{credentials}" if co_id.nil?
60
+ resource_label = "companies/#{co_id}/libraries"
61
+ end
62
+ "#{base_url}/#{resource_label}"
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -2,26 +2,27 @@ require 'helix/video'
2
2
  require 'helix/track'
3
3
  require 'helix/album'
4
4
  require 'helix/image'
5
+ require 'helix/builds_urls'
6
+ require 'helix/has_signatures'
7
+ require 'helix/paginates'
5
8
  require 'singleton'
6
9
 
7
10
  module Helix
8
11
 
9
12
  class Config
10
13
 
14
+ include BuildsUrls
15
+ include HasSignatures
16
+ include Paginates
11
17
  include Singleton
12
18
 
13
19
  unless defined?(self::DEFAULT_FILENAME)
14
20
  DEFAULT_FILENAME = './helix.yml'
15
- ITEMS_PER_PAGE = 100
16
- SCOPES = [:reseller, :company, :library]
17
- SIG_DURATION = 1200 # in minutes
18
- STARTING_PAGE = 1
19
- TIME_OFFSET = 1000 * 60 # 1000 minutes, lower to give some margin of error
20
- VALID_SIG_TYPES = [ :ingest, :update, :view ]
21
21
  end
22
22
 
23
- attr_accessor :credentials
24
- attr_reader :response, :signature_for, :signature_expiration_for
23
+ attr_accessor :credentials # local
24
+ attr_reader :response # in Paginates
25
+ attr_reader :signature_for, :signature_expiration_for # in HasSignatures
25
26
 
26
27
  # Creates a singleton of itself, setting the config
27
28
  # to a specified YAML file. If no file is specified the default
@@ -42,122 +43,6 @@ module Helix
42
43
  config
43
44
  end
44
45
 
45
- # Creates additional URL stubbing that can be used in conjuction
46
- # with the base_url to create RESTful URLs
47
- #
48
- # @param [String] base_url the base part of the URL to be used
49
- # @param [Hash] opts a hash of options for building URL additions
50
- # @return [String] The full RESTful URL string object
51
- def add_sub_urls(base_url, opts)
52
- guid, action, format = [:guid, :action, :formats].map { |sub| opts[sub] }
53
- url = sub_url_scoping(base_url, opts)
54
- url += "/#{guid}" if guid
55
- url += "/formats/#{format}" if format
56
- url += "/#{action}" if action
57
- return url if opts[:content_type].blank?
58
- "#{url}.#{opts[:content_type]}"
59
- end
60
-
61
- # Creates a full RESTful URL to be used for HTTP requests.
62
- #
63
- # @param [Hash] opts a hash of options for building URL
64
- # @return [String] The full RESTful URL string object
65
- def build_url(opts={})
66
- opts[:content_type] ||= :xml
67
- opts[:resource_label] ||= :videos
68
- base_url = get_base_url(opts)
69
- url = add_sub_urls(base_url, opts)
70
- end
71
-
72
- def clear_signatures!
73
- @signature_for = {}
74
- @signature_expiration_for = {}
75
- end
76
-
77
- # Makes aggregated calls to get_response with pagination
78
- # folding/injecting/accumulating the results into a single output set.
79
- #
80
- # @param [String] url the base part of the URL to be used
81
- # @param [String] plural_resource_label: "videos", "tracks", etc.
82
- # @param [Hash] original_opts a hash of options for building URL additions
83
- # @return [Array] The accumulated attribute Hashes for ORM instances
84
- def get_aggregated_data_sets(url, plural_resource_label, original_opts={})
85
- data_sets, page, per_page = [], STARTING_PAGE
86
- begin
87
- aggregation_opts = {page: page, per_page: ITEMS_PER_PAGE}.merge(original_opts)
88
- raw_response = get_response(url, {sig_type: :view}.merge(aggregation_opts))
89
- data_set = raw_response[plural_resource_label]
90
- data_sets += data_set if data_set
91
- page += 1
92
- end until last_page?
93
- data_sets
94
- end
95
-
96
- # Creates the base url with information collected from credentials.
97
- #
98
- # @param [Hash] opts a hash of options for building URL
99
- # @return [String] The base RESTful URL string object
100
- def get_base_url(opts)
101
- creds = credentials
102
- base_url = creds[:site]
103
- return base_url if opts[:guid] || opts[:action] == :create_many
104
- reseller, company, library = SCOPES.map { |scope| creds[scope] }
105
- base_url += "/resellers/#{reseller}" if reseller
106
- if company
107
- base_url += "/companies/#{company}"
108
- base_url += "/libraries/#{library}" if library
109
- end
110
- base_url
111
- end
112
-
113
- # Creates additional URL stubbing that can be used in conjuction
114
- # with the base_url to create RESTful URLs
115
- #
116
- # @param [String] url the base part of the URL to be used
117
- # @param [Hash] original_opts a hash of options for building URL additions
118
- # @return [String] The full RESTful URL string object
119
- def get_response(url, original_opts={})
120
- opts = massage_custom_fields_in(original_opts)
121
- sig_type = opts.delete(:sig_type)
122
- params = opts.merge(signature: signature(sig_type, opts))
123
- begin
124
- @response = RestClient.get(url, params: params)
125
- rescue RestClient::InternalServerError => e
126
- raise NetworkError, "Unable to access url #{url} with params #{params}"
127
- end
128
- parse_response_by_url_format(@response, url)
129
- end
130
-
131
- # Reports whether the most recent response's headers have a true :is_last_page value
132
- #
133
- # @return [Boolean] As above. Returns false if no such header is found,
134
- # or if there is an explictly false value.
135
- def last_page?
136
- return false unless @response
137
- return false unless @response.headers
138
- return true unless @response.headers.has_key?(:is_last_page)
139
- @response.headers[:is_last_page] == "true"
140
- end
141
-
142
- # Fetches the signature for a specific license key.
143
- #
144
- # @param [Symbol] sig_type The type of signature required for calls.
145
- # @param [Hash] opts allows you to overide contributor and license_id
146
- # @return [String] The signature needed to pass around for calls.
147
- def signature(sig_type, opts={})
148
- prepare_signature_memoization
149
- memo_sig = existing_sig_for(sig_type)
150
- return memo_sig if memo_sig
151
- unless VALID_SIG_TYPES.include?(sig_type)
152
- raise ArgumentError, error_message_for(sig_type)
153
- end
154
-
155
- lk = license_key
156
- @signature_expiration_for[lk][sig_type] = Time.now + TIME_OFFSET
157
- new_sig_url = url_for(sig_type, opts)
158
- @signature_for[lk][sig_type] = RestClient.get(new_sig_url)
159
- end
160
-
161
46
  def proxy
162
47
  if @credentials[:proxy_uri]
163
48
  protocol, uri = @credentials[:proxy_uri].split "://"
@@ -172,88 +57,6 @@ module Helix
172
57
  end
173
58
  end
174
59
 
175
- private
176
-
177
- def sub_url_scoping(base_url, opts)
178
- resource_label = opts[:resource_label]
179
- if resource_label == 'libraries' and base_url !~ /companies/
180
- co_id = opts[:company] || credentials[:company]
181
- raise "No company to scope to: #{credentials}" if co_id.nil?
182
- resource_label = "companies/#{co_id}/libraries"
183
- end
184
- "#{base_url}/#{resource_label}"
185
- end
186
-
187
- def error_message_for(sig_type)
188
- "I don't understand '#{sig_type}'. Please give me one of :ingest, :update, or :view."
189
- end
190
-
191
- def existing_sig_for(sig_type)
192
- return if sig_expired_for?(sig_type)
193
- @signature_for[license_key][sig_type]
194
- end
195
-
196
- def get_contributor_library_company(opts)
197
- sig_param_labels = [:contributor, :library, :company]
198
- scoping_proc = lambda { |key| opts[key] || credentials[key] }
199
- contributor, library, company = sig_param_labels.map(&scoping_proc)
200
- contributor ||= 'helix_default_contributor'
201
- [contributor, library, company]
202
- end
203
-
204
- def license_key
205
- @credentials[:license_key]
206
- end
207
-
208
- def massage_custom_fields_in(opts)
209
- return opts.clone unless opts.has_key?(:custom_fields)
210
- cf_opts = opts.delete(:custom_fields)
211
- cf_opts.inject(opts.clone) do |memo,pair|
212
- k,v = pair
213
- memo.merge("custom_fields[#{k}]" => v)
214
- end
215
- end
216
-
217
- def parse_response_by_url_format(response, url)
218
- ### FIXME: This is ugly. Clean it up.
219
- if url =~ /json/
220
- JSON.parse(response)
221
- elsif url =~ /xml/
222
- #TODO: Cleanup Nori and response gsub.
223
- Nori.parser = :nokogiri
224
- xml = response.gsub(/<custom-fields type='array'>/, '<custom-fields type=\'hash\'>')
225
- Nori.parse(xml)
226
- elsif url =~ /csv/
227
- response
228
- else
229
- raise "Could not parse #{url}"
230
- end
231
- end
232
-
233
- def prepare_signature_memoization
234
- lk = license_key
235
- @signature_for ||= {}
236
- @signature_expiration_for ||= {}
237
- @signature_for[lk] ||= {}
238
- @signature_expiration_for[lk] ||= {}
239
- end
240
-
241
- def sig_expired_for?(sig_type)
242
- expires_at = @signature_expiration_for[license_key][sig_type]
243
- return true if expires_at.nil?
244
- expires_at <= Time.now
245
- end
246
-
247
- def url_for(sig_type, opts={})
248
- contributor, library, company = get_contributor_library_company(opts)
249
- url = "#{credentials[:site]}/api/#{sig_type}_key?"
250
- url += "licenseKey=#{credentials[:license_key]}&duration=#{SIG_DURATION}"
251
- url += "&contributor=#{contributor}" if sig_type == :ingest
252
- url += "&library_id=#{library}" if library
253
- url += "&company_id=#{company}" if company
254
- url
255
- end
256
-
257
60
  end
258
61
 
259
62
  end
@@ -0,0 +1,84 @@
1
+ module Helix
2
+
3
+ module HasSignatures
4
+
5
+ unless defined?(self::VALID_SIG_TYPES)
6
+ SIG_DURATION = 1200 # in minutes
7
+ TIME_OFFSET = 1000 * 60 # 1000 minutes, lower to give some margin of error
8
+ VALID_SIG_TYPES = [ :ingest, :update, :view ]
9
+ end
10
+
11
+ def clear_signatures!
12
+ @signature_for = {}
13
+ @signature_expiration_for = {}
14
+ end
15
+
16
+ # Fetches the signature for a specific license key.
17
+ #
18
+ # @param [Symbol] sig_type The type of signature required for calls.
19
+ # @param [Hash] opts allows you to overide contributor and license_id
20
+ # @return [String] The signature needed to pass around for calls.
21
+ def signature(sig_type, opts={})
22
+ prepare_signature_memoization
23
+ memo_sig = existing_sig_for(sig_type)
24
+ return memo_sig if memo_sig
25
+ unless VALID_SIG_TYPES.include?(sig_type)
26
+ raise ArgumentError, error_message_for(sig_type)
27
+ end
28
+
29
+ lk = license_key
30
+ @signature_expiration_for[lk][sig_type] = Time.now + TIME_OFFSET
31
+ new_sig_url = signature_url_for(sig_type, opts)
32
+ @signature_for[lk][sig_type] = RestClient.get(new_sig_url)
33
+ end
34
+
35
+ private
36
+
37
+ def error_message_for(sig_type)
38
+ "I don't understand '#{sig_type}'. Please give me one of :ingest, :update, or :view."
39
+ end
40
+
41
+ def existing_sig_for(sig_type)
42
+ return if sig_expired_for?(sig_type)
43
+ @signature_for[license_key][sig_type]
44
+ end
45
+
46
+ def get_contributor_library_company(opts)
47
+ sig_param_labels = [:contributor, :library, :company]
48
+ scoping_proc = lambda { |key| opts[key] || credentials[key] }
49
+ contributor, library, company = sig_param_labels.map(&scoping_proc)
50
+ contributor ||= 'helix_default_contributor'
51
+ [contributor, library, company]
52
+ end
53
+
54
+ def license_key
55
+ @credentials[:license_key]
56
+ end
57
+
58
+ def prepare_signature_memoization
59
+ lk = license_key
60
+ @signature_for ||= {}
61
+ @signature_expiration_for ||= {}
62
+ @signature_for[lk] ||= {}
63
+ @signature_expiration_for[lk] ||= {}
64
+ end
65
+
66
+ def sig_expired_for?(sig_type)
67
+ expires_at = @signature_expiration_for[license_key][sig_type]
68
+ return true if expires_at.nil?
69
+ expires_at <= Time.now
70
+ end
71
+
72
+ def signature_url_for(sig_type, opts={})
73
+ contributor, library, company = get_contributor_library_company(opts)
74
+ url = "#{credentials[:site]}/api/#{sig_type}_key?"
75
+ url += "licenseKey=#{credentials[:license_key]}&duration=#{SIG_DURATION}"
76
+ url += "&contributor=#{contributor}" if sig_type == :ingest
77
+ url += "&library_id=#{library}" if library
78
+ url += "&company_id=#{company}" if company
79
+ url
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -13,6 +13,16 @@ module Helix
13
13
  super(nickname, opts.merge(content_type: :xml))
14
14
  end
15
15
 
16
+ # Creates a string that associates to the class id.
17
+ #
18
+ # @example
19
+ # Helix::Library.guid_name #=> "name"
20
+ #
21
+ # @return [String] The guid name for a specific class.
22
+ def self.guid_name
23
+ "name"
24
+ end
25
+
16
26
  # The class name, to be used by supporting classes. Such as Config which uses
17
27
  # this method as a way to build URLs.
18
28
  #
@@ -33,6 +43,7 @@ module Helix
33
43
  "libraries"
34
44
  end
35
45
 
46
+ #TODO: Revisit and document.
36
47
  def self.known_attributes
37
48
  [:player_profile, :ingest_profile, :secure_stream_callback_url, :hooks_attributes]
38
49
  end
@@ -0,0 +1,91 @@
1
+ module Helix
2
+
3
+ module Paginates
4
+
5
+ unless defined?(self::STARTING_PAGE)
6
+ ITEMS_PER_PAGE = 100
7
+ STARTING_PAGE = 1
8
+ end
9
+
10
+ # Makes aggregated calls to get_response with pagination
11
+ # folding/injecting/accumulating the results into a single output set.
12
+ #
13
+ # @param [String] url the base part of the URL to be used
14
+ # @param [String] plural_resource_label: "videos", "tracks", etc.
15
+ # @param [Hash] original_opts a hash of options for building URL additions
16
+ # @return [Array] The accumulated attribute Hashes for ORM instances
17
+ def get_aggregated_data_sets(url, plural_resource_label, original_opts={})
18
+ data_sets, page, per_page = [], STARTING_PAGE
19
+ begin
20
+ aggregation_opts = {page: page, per_page: ITEMS_PER_PAGE}.merge(original_opts)
21
+ raw_response = get_response(url, {sig_type: :view}.merge(aggregation_opts))
22
+ data_set = raw_response[plural_resource_label]
23
+ data_sets += data_set if data_set
24
+ page += 1
25
+ end until last_page? || specific_page_requested?(original_opts)
26
+ data_sets
27
+ end
28
+
29
+ # Creates additional URL stubbing that can be used in conjuction
30
+ # with the base_url to create RESTful URLs
31
+ #
32
+ # @param [String] url the base part of the URL to be used
33
+ # @param [Hash] original_opts a hash of options for building URL additions
34
+ # @return [String] The full RESTful URL string object
35
+ def get_response(url, original_opts={})
36
+ opts = massage_custom_fields_in(original_opts)
37
+ sig_type = opts.delete(:sig_type)
38
+ params = opts.merge(signature: signature(sig_type, opts))
39
+ begin
40
+ @response = RestClient.get(url, params: params)
41
+ rescue RestClient::InternalServerError => e
42
+ raise NetworkError, "Unable to access url #{url} with params #{params}"
43
+ end
44
+ parse_response_by_url_format(@response, url)
45
+ end
46
+
47
+ private
48
+
49
+ # Reports whether the most recent response's headers have a true :is_last_page value
50
+ #
51
+ # @return [Boolean] As above. Returns false if no such header is found,
52
+ # or if there is an explictly false value.
53
+ def last_page?
54
+ return false unless @response
55
+ return false unless @response.headers
56
+ return true unless @response.headers.has_key?(:is_last_page)
57
+ @response.headers[:is_last_page] == "true"
58
+ end
59
+
60
+ def massage_custom_fields_in(opts)
61
+ return opts.clone unless opts.has_key?(:custom_fields)
62
+ cf_opts = opts.delete(:custom_fields)
63
+ cf_opts.inject(opts.clone) do |memo,pair|
64
+ k,v = pair
65
+ memo.merge("custom_fields[#{k}]" => v)
66
+ end
67
+ end
68
+
69
+ def specific_page_requested?(original_opts)
70
+ original_opts.has_key?(:page)
71
+ end
72
+
73
+ def parse_response_by_url_format(response, url)
74
+ ### FIXME: This is ugly. Clean it up.
75
+ if url =~ /json/
76
+ JSON.parse(response)
77
+ elsif url =~ /xml/
78
+ #TODO: Cleanup Nori and response gsub.
79
+ Nori.parser = :nokogiri
80
+ xml = response.gsub(/<custom-fields type='array'>/, '<custom-fields type=\'hash\'>')
81
+ Nori.parse(xml)
82
+ elsif url =~ /csv/
83
+ response
84
+ else
85
+ raise "Could not parse #{url}"
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -289,6 +289,11 @@ describe Helix::Base do
289
289
  subject { obj.send(meth, raw_attrs) }
290
290
  it { should eq(nil) }
291
291
  end
292
+ context "when given {'site' => :site_contents}" do
293
+ let(:raw_attrs) { {'site' => :site_contents} }
294
+ subject { obj.send(meth, raw_attrs) }
295
+ it { should eq(:site_contents) }
296
+ end
292
297
  context "when given { guid_name => :the_val }" do
293
298
  let(:raw_attrs) { { guid_name => :the_val } }
294
299
  subject { obj.send(meth, raw_attrs) }
@@ -336,34 +336,6 @@ describe Helix::Config do
336
336
  end
337
337
  end
338
338
 
339
- describe "#get_aggregated_data_sets" do
340
- let(:meth) { :get_aggregated_data_sets }
341
- subject { obj.method(meth) }
342
- its(:arity) { should eq(-3) }
343
- context "when called" do
344
- let(:opts) { {opts_key1: :opts_val1, per_page: 99} }
345
- let(:label) { :videos }
346
- before(:each) do
347
- obj.stub(:signature) { :the_sig }
348
- end
349
- subject { obj.send(meth, :a_url, label, opts) }
350
- it "should successively call RestClient.get with the opts arg merged with pagination info and return the parsed results" do
351
- base_opts = {opts_key1: :opts_val1, per_page: 99, signature: :the_sig}
352
- opts1 = {params: base_opts.merge(page: 1)}
353
- opts2 = {params: base_opts.merge(page: 2)}
354
- opts3 = {params: base_opts.merge(page: 3)}
355
- non_final_response = double(String, headers: {is_last_page: 'false'})
356
- final_response = double(String, headers: {is_last_page: 'true'})
357
- RestClient.should_receive(:get).with(:a_url, opts1) { non_final_response }
358
- RestClient.should_receive(:get).with(:a_url, opts2) { non_final_response }
359
- RestClient.should_receive(:get).with(:a_url, opts3) { final_response }
360
- obj.stub(:parse_response_by_url_format).with(non_final_response, :a_url) { {label => [:non_final]} }
361
- obj.stub(:parse_response_by_url_format).with(final_response, :a_url) { {label => [:final]} }
362
- expect(obj.send(meth, :a_url, label, opts)).to eq([:non_final, :non_final, :final])
363
- end
364
- end
365
- end
366
-
367
339
  describe "#get_response" do
368
340
  let(:meth) { :get_response }
369
341
  subject { obj.method(meth) }
@@ -10,7 +10,7 @@ describe Helix::Library do
10
10
  mods.each { |mod| its(:ancestors) { should include(mod) } }
11
11
  its(:ancestors) { should_not include(Helix::Media) }
12
12
 
13
- its(:guid_name) { should eq('library_id') }
13
+ its(:guid_name) { should eq('name') }
14
14
  its(:resource_label_sym) { should be(:library) }
15
15
  its(:plural_resource_label) { should eq('libraries') }
16
16
  [:find, :create, :all, :find_all, :where].each do |crud_call|
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'helix'
3
+
4
+ describe Helix::Paginates do
5
+
6
+ class DummyClass;end
7
+
8
+ before(:each) do
9
+ @klass = DummyClass.new
10
+ @klass.extend(Helix::Paginates)
11
+ end
12
+
13
+
14
+ describe "#get_aggregated_data_sets" do
15
+ let(:meth) { :get_aggregated_data_sets }
16
+ subject { @klass.method(meth) }
17
+ its(:arity) { should eq(-3) }
18
+ context "when called" do
19
+ let(:opts) { {opts_key1: :opts_val1, per_page: 99} }
20
+ let(:label) { :videos }
21
+ let(:base_opts) { {opts_key1: :opts_val1, per_page: 99, signature: :the_sig} }
22
+ let(:opts1) { {params: base_opts.merge(page: 1)} }
23
+ let(:opts2) { {params: base_opts.merge(page: 2)} }
24
+ let(:opts3) { {params: base_opts.merge(page: 3)} }
25
+ before(:each) { @klass.stub(:signature) { :the_sig } }
26
+ subject { @klass.send(meth, :a_url, label, opts) }
27
+ it "should successively call RestClient.get with the opts arg merged with pagination info and return the parsed results" do
28
+ non_final_response = double(String, headers: {is_last_page: 'false'})
29
+ final_response = double(String, headers: {is_last_page: 'true'})
30
+ RestClient.should_receive(:get).with(:a_url, opts1) { non_final_response }
31
+ RestClient.should_receive(:get).with(:a_url, opts2) { non_final_response }
32
+ RestClient.should_receive(:get).with(:a_url, opts3) { final_response }
33
+ @klass.stub(:parse_response_by_url_format).with(non_final_response, :a_url) { {label => [:non_final]} }
34
+ @klass.stub(:parse_response_by_url_format).with(final_response, :a_url) { {label => [:final]} }
35
+ expect(@klass.send(meth, :a_url, label, opts)).to eq([:non_final, :non_final, :final])
36
+ end
37
+
38
+ context "when a page param is passed in." do
39
+ let(:opts) { {opts_key1: :opts_val1, page: 1} }
40
+ it "should only return one response" do
41
+ base_opts = {opts_key1: :opts_val1, per_page: 100, signature: :the_sig}
42
+ opts1 = {params: base_opts.merge(page: 1)}
43
+ non_final_response = double(String, headers: {is_last_page: 'false'})
44
+ RestClient.should_receive(:get).once { non_final_response }
45
+ @klass.stub(:parse_response_by_url_format).with(non_final_response, :a_url) { {label => [:non_final]} }
46
+ @klass.send(meth, :a_url, label, opts)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: helix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.3.pre
4
+ version: 0.0.4.4.pre
5
5
  prerelease: 8
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-11 00:00:00.000000000 Z
12
+ date: 2013-09-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -69,15 +69,18 @@ files:
69
69
  - lib/helix/album.rb
70
70
  - lib/helix/audio_playlist.rb
71
71
  - lib/helix/base.rb
72
+ - lib/helix/builds_urls.rb
72
73
  - lib/helix/config.rb
73
74
  - lib/helix/document.rb
74
75
  - lib/helix/durationed.rb
75
76
  - lib/helix/exceptions.rb
77
+ - lib/helix/has_signatures.rb
76
78
  - lib/helix/hash_ext.rb
77
79
  - lib/helix/image.rb
78
80
  - lib/helix/library.rb
79
81
  - lib/helix/media.rb
80
82
  - lib/helix/object_ext.rb
83
+ - lib/helix/paginates.rb
81
84
  - lib/helix/playlist.rb
82
85
  - lib/helix/restful.rb
83
86
  - lib/helix/statistics.rb
@@ -98,6 +101,7 @@ files:
98
101
  - spec/image_spec.rb
99
102
  - spec/library_spec.rb
100
103
  - spec/media_spec.rb
104
+ - spec/paginates_spec.rb
101
105
  - spec/playlist_spec.rb
102
106
  - spec/spec_helper.rb
103
107
  - spec/statistics_spec.rb