helix 0.0.4.3.pre → 0.0.4.4.pre

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