##// END OF EJS Templates
Use assert_nil instead of assert_equal....
Jean-Philippe Lang -
r15677:e937cb533efa
parent child
Show More
@@ -1,401 +1,401
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 if ENV["COVERAGE"]
18 if ENV["COVERAGE"]
19 require 'simplecov'
19 require 'simplecov'
20 require File.expand_path(File.dirname(__FILE__) + "/coverage/html_formatter")
20 require File.expand_path(File.dirname(__FILE__) + "/coverage/html_formatter")
21 SimpleCov.formatter = Redmine::Coverage::HtmlFormatter
21 SimpleCov.formatter = Redmine::Coverage::HtmlFormatter
22 SimpleCov.start 'rails'
22 SimpleCov.start 'rails'
23 end
23 end
24
24
25 $redmine_test_ldap_server = ENV['REDMINE_TEST_LDAP_SERVER'] || '127.0.0.1'
25 $redmine_test_ldap_server = ENV['REDMINE_TEST_LDAP_SERVER'] || '127.0.0.1'
26
26
27 ENV["RAILS_ENV"] = "test"
27 ENV["RAILS_ENV"] = "test"
28 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
28 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
29 require 'rails/test_help'
29 require 'rails/test_help'
30 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
30 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
31
31
32 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
32 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
33 include ObjectHelpers
33 include ObjectHelpers
34
34
35 require 'net/ldap'
35 require 'net/ldap'
36 require 'mocha/setup'
36 require 'mocha/setup'
37
37
38 Redmine::SudoMode.disable!
38 Redmine::SudoMode.disable!
39
39
40 class ActionView::TestCase
40 class ActionView::TestCase
41 helper :application
41 helper :application
42 include ApplicationHelper
42 include ApplicationHelper
43 end
43 end
44
44
45 class ActiveSupport::TestCase
45 class ActiveSupport::TestCase
46 include ActionDispatch::TestProcess
46 include ActionDispatch::TestProcess
47
47
48 self.use_transactional_fixtures = true
48 self.use_transactional_fixtures = true
49 self.use_instantiated_fixtures = false
49 self.use_instantiated_fixtures = false
50
50
51 def uploaded_test_file(name, mime)
51 def uploaded_test_file(name, mime)
52 fixture_file_upload("files/#{name}", mime, true)
52 fixture_file_upload("files/#{name}", mime, true)
53 end
53 end
54
54
55 # Mock out a file
55 # Mock out a file
56 def self.mock_file
56 def self.mock_file
57 file = 'a_file.png'
57 file = 'a_file.png'
58 file.stubs(:size).returns(32)
58 file.stubs(:size).returns(32)
59 file.stubs(:original_filename).returns('a_file.png')
59 file.stubs(:original_filename).returns('a_file.png')
60 file.stubs(:content_type).returns('image/png')
60 file.stubs(:content_type).returns('image/png')
61 file.stubs(:read).returns(false)
61 file.stubs(:read).returns(false)
62 file
62 file
63 end
63 end
64
64
65 def mock_file
65 def mock_file
66 self.class.mock_file
66 self.class.mock_file
67 end
67 end
68
68
69 def mock_file_with_options(options={})
69 def mock_file_with_options(options={})
70 file = ''
70 file = ''
71 file.stubs(:size).returns(32)
71 file.stubs(:size).returns(32)
72 original_filename = options[:original_filename] || nil
72 original_filename = options[:original_filename] || nil
73 file.stubs(:original_filename).returns(original_filename)
73 file.stubs(:original_filename).returns(original_filename)
74 content_type = options[:content_type] || nil
74 content_type = options[:content_type] || nil
75 file.stubs(:content_type).returns(content_type)
75 file.stubs(:content_type).returns(content_type)
76 file.stubs(:read).returns(false)
76 file.stubs(:read).returns(false)
77 file
77 file
78 end
78 end
79
79
80 # Use a temporary directory for attachment related tests
80 # Use a temporary directory for attachment related tests
81 def set_tmp_attachments_directory
81 def set_tmp_attachments_directory
82 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
82 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
83 unless File.directory?("#{Rails.root}/tmp/test/attachments")
83 unless File.directory?("#{Rails.root}/tmp/test/attachments")
84 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
84 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
85 end
85 end
86 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
86 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
87 end
87 end
88
88
89 def set_fixtures_attachments_directory
89 def set_fixtures_attachments_directory
90 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
90 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
91 end
91 end
92
92
93 def with_settings(options, &block)
93 def with_settings(options, &block)
94 saved_settings = options.keys.inject({}) do |h, k|
94 saved_settings = options.keys.inject({}) do |h, k|
95 h[k] = case Setting[k]
95 h[k] = case Setting[k]
96 when Symbol, false, true, nil
96 when Symbol, false, true, nil
97 Setting[k]
97 Setting[k]
98 else
98 else
99 Setting[k].dup
99 Setting[k].dup
100 end
100 end
101 h
101 h
102 end
102 end
103 options.each {|k, v| Setting[k] = v}
103 options.each {|k, v| Setting[k] = v}
104 yield
104 yield
105 ensure
105 ensure
106 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
106 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
107 end
107 end
108
108
109 # Yields the block with user as the current user
109 # Yields the block with user as the current user
110 def with_current_user(user, &block)
110 def with_current_user(user, &block)
111 saved_user = User.current
111 saved_user = User.current
112 User.current = user
112 User.current = user
113 yield
113 yield
114 ensure
114 ensure
115 User.current = saved_user
115 User.current = saved_user
116 end
116 end
117
117
118 def with_locale(locale, &block)
118 def with_locale(locale, &block)
119 saved_localed = ::I18n.locale
119 saved_localed = ::I18n.locale
120 ::I18n.locale = locale
120 ::I18n.locale = locale
121 yield
121 yield
122 ensure
122 ensure
123 ::I18n.locale = saved_localed
123 ::I18n.locale = saved_localed
124 end
124 end
125
125
126 def self.ldap_configured?
126 def self.ldap_configured?
127 @test_ldap = Net::LDAP.new(:host => $redmine_test_ldap_server, :port => 389)
127 @test_ldap = Net::LDAP.new(:host => $redmine_test_ldap_server, :port => 389)
128 return @test_ldap.bind
128 return @test_ldap.bind
129 rescue Exception => e
129 rescue Exception => e
130 # LDAP is not listening
130 # LDAP is not listening
131 return nil
131 return nil
132 end
132 end
133
133
134 def self.convert_installed?
134 def self.convert_installed?
135 Redmine::Thumbnail.convert_available?
135 Redmine::Thumbnail.convert_available?
136 end
136 end
137
137
138 def convert_installed?
138 def convert_installed?
139 self.class.convert_installed?
139 self.class.convert_installed?
140 end
140 end
141
141
142 # Returns the path to the test +vendor+ repository
142 # Returns the path to the test +vendor+ repository
143 def self.repository_path(vendor)
143 def self.repository_path(vendor)
144 path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
144 path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
145 # Unlike ruby, JRuby returns Rails.root with backslashes under Windows
145 # Unlike ruby, JRuby returns Rails.root with backslashes under Windows
146 path.tr("\\", "/")
146 path.tr("\\", "/")
147 end
147 end
148
148
149 # Returns the url of the subversion test repository
149 # Returns the url of the subversion test repository
150 def self.subversion_repository_url
150 def self.subversion_repository_url
151 path = repository_path('subversion')
151 path = repository_path('subversion')
152 path = '/' + path unless path.starts_with?('/')
152 path = '/' + path unless path.starts_with?('/')
153 "file://#{path}"
153 "file://#{path}"
154 end
154 end
155
155
156 # Returns true if the +vendor+ test repository is configured
156 # Returns true if the +vendor+ test repository is configured
157 def self.repository_configured?(vendor)
157 def self.repository_configured?(vendor)
158 File.directory?(repository_path(vendor))
158 File.directory?(repository_path(vendor))
159 end
159 end
160
160
161 def repository_path_hash(arr)
161 def repository_path_hash(arr)
162 hs = {}
162 hs = {}
163 hs[:path] = arr.join("/")
163 hs[:path] = arr.join("/")
164 hs[:param] = arr.join("/")
164 hs[:param] = arr.join("/")
165 hs
165 hs
166 end
166 end
167
167
168 def sqlite?
168 def sqlite?
169 ActiveRecord::Base.connection.adapter_name =~ /sqlite/i
169 ActiveRecord::Base.connection.adapter_name =~ /sqlite/i
170 end
170 end
171
171
172 def mysql?
172 def mysql?
173 ActiveRecord::Base.connection.adapter_name =~ /mysql/i
173 ActiveRecord::Base.connection.adapter_name =~ /mysql/i
174 end
174 end
175
175
176 def postgresql?
176 def postgresql?
177 ActiveRecord::Base.connection.adapter_name =~ /postgresql/i
177 ActiveRecord::Base.connection.adapter_name =~ /postgresql/i
178 end
178 end
179
179
180 def quoted_date(date)
180 def quoted_date(date)
181 date = Date.parse(date) if date.is_a?(String)
181 date = Date.parse(date) if date.is_a?(String)
182 ActiveRecord::Base.connection.quoted_date(date)
182 ActiveRecord::Base.connection.quoted_date(date)
183 end
183 end
184
184
185 # Asserts that a new record for the given class is created
185 # Asserts that a new record for the given class is created
186 # and returns it
186 # and returns it
187 def new_record(klass, &block)
187 def new_record(klass, &block)
188 new_records(klass, 1, &block).first
188 new_records(klass, 1, &block).first
189 end
189 end
190
190
191 # Asserts that count new records for the given class are created
191 # Asserts that count new records for the given class are created
192 # and returns them as an array order by object id
192 # and returns them as an array order by object id
193 def new_records(klass, count, &block)
193 def new_records(klass, count, &block)
194 assert_difference "#{klass}.count", count do
194 assert_difference "#{klass}.count", count do
195 yield
195 yield
196 end
196 end
197 klass.order(:id => :desc).limit(count).to_a.reverse
197 klass.order(:id => :desc).limit(count).to_a.reverse
198 end
198 end
199
199
200 def assert_save(object)
200 def assert_save(object)
201 saved = object.save
201 saved = object.save
202 message = "#{object.class} could not be saved"
202 message = "#{object.class} could not be saved"
203 errors = object.errors.full_messages.map {|m| "- #{m}"}
203 errors = object.errors.full_messages.map {|m| "- #{m}"}
204 message << ":\n#{errors.join("\n")}" if errors.any?
204 message << ":\n#{errors.join("\n")}" if errors.any?
205 assert_equal true, saved, message
205 assert_equal true, saved, message
206 end
206 end
207
207
208 def assert_select_error(arg)
208 def assert_select_error(arg)
209 assert_select '#errorExplanation', :text => arg
209 assert_select '#errorExplanation', :text => arg
210 end
210 end
211
211
212 def assert_include(expected, s, message=nil)
212 def assert_include(expected, s, message=nil)
213 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
213 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
214 end
214 end
215
215
216 def assert_not_include(expected, s, message=nil)
216 def assert_not_include(expected, s, message=nil)
217 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
217 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
218 end
218 end
219
219
220 def assert_select_in(text, *args, &block)
220 def assert_select_in(text, *args, &block)
221 d = Nokogiri::HTML(CGI::unescapeHTML(String.new(text))).root
221 d = Nokogiri::HTML(CGI::unescapeHTML(String.new(text))).root
222 assert_select(d, *args, &block)
222 assert_select(d, *args, &block)
223 end
223 end
224
224
225 def assert_select_email(*args, &block)
225 def assert_select_email(*args, &block)
226 email = ActionMailer::Base.deliveries.last
226 email = ActionMailer::Base.deliveries.last
227 assert_not_nil email
227 assert_not_nil email
228 html_body = email.parts.detect {|part| part.content_type.include?('text/html')}.try(&:body)
228 html_body = email.parts.detect {|part| part.content_type.include?('text/html')}.try(&:body)
229 assert_not_nil html_body
229 assert_not_nil html_body
230 assert_select_in html_body.encoded, *args, &block
230 assert_select_in html_body.encoded, *args, &block
231 end
231 end
232
232
233 def assert_mail_body_match(expected, mail, message=nil)
233 def assert_mail_body_match(expected, mail, message=nil)
234 if expected.is_a?(String)
234 if expected.is_a?(String)
235 assert_include expected, mail_body(mail), message
235 assert_include expected, mail_body(mail), message
236 else
236 else
237 assert_match expected, mail_body(mail), message
237 assert_match expected, mail_body(mail), message
238 end
238 end
239 end
239 end
240
240
241 def assert_mail_body_no_match(expected, mail, message=nil)
241 def assert_mail_body_no_match(expected, mail, message=nil)
242 if expected.is_a?(String)
242 if expected.is_a?(String)
243 assert_not_include expected, mail_body(mail), message
243 assert_not_include expected, mail_body(mail), message
244 else
244 else
245 assert_no_match expected, mail_body(mail), message
245 assert_no_match expected, mail_body(mail), message
246 end
246 end
247 end
247 end
248
248
249 def mail_body(mail)
249 def mail_body(mail)
250 mail.parts.first.body.encoded
250 mail.parts.first.body.encoded
251 end
251 end
252
252
253 # Returns the lft value for a new root issue
253 # Returns the lft value for a new root issue
254 def new_issue_lft
254 def new_issue_lft
255 1
255 1
256 end
256 end
257 end
257 end
258
258
259 module Redmine
259 module Redmine
260 class RoutingTest < ActionDispatch::IntegrationTest
260 class RoutingTest < ActionDispatch::IntegrationTest
261 def should_route(arg)
261 def should_route(arg)
262 arg = arg.dup
262 arg = arg.dup
263 request = arg.keys.detect {|key| key.is_a?(String)}
263 request = arg.keys.detect {|key| key.is_a?(String)}
264 raise ArgumentError unless request
264 raise ArgumentError unless request
265 options = arg.slice!(request)
265 options = arg.slice!(request)
266
266
267 raise ArgumentError unless request =~ /\A(GET|POST|PUT|PATCH|DELETE)\s+(.+)\z/
267 raise ArgumentError unless request =~ /\A(GET|POST|PUT|PATCH|DELETE)\s+(.+)\z/
268 method, path = $1.downcase.to_sym, $2
268 method, path = $1.downcase.to_sym, $2
269
269
270 raise ArgumentError unless arg.values.first =~ /\A(.+)#(.+)\z/
270 raise ArgumentError unless arg.values.first =~ /\A(.+)#(.+)\z/
271 controller, action = $1, $2
271 controller, action = $1, $2
272
272
273 assert_routing(
273 assert_routing(
274 {:method => method, :path => path},
274 {:method => method, :path => path},
275 options.merge(:controller => controller, :action => action)
275 options.merge(:controller => controller, :action => action)
276 )
276 )
277 end
277 end
278 end
278 end
279
279
280 class HelperTest < ActionView::TestCase
280 class HelperTest < ActionView::TestCase
281
281
282 end
282 end
283
283
284 class ControllerTest < ActionController::TestCase
284 class ControllerTest < ActionController::TestCase
285 # Returns the issues that are displayed in the list in the same order
285 # Returns the issues that are displayed in the list in the same order
286 def issues_in_list
286 def issues_in_list
287 ids = css_select('tr.issue td.id').map(&:text).map(&:to_i)
287 ids = css_select('tr.issue td.id').map(&:text).map(&:to_i)
288 Issue.where(:id => ids).sort_by {|issue| ids.index(issue.id)}
288 Issue.where(:id => ids).sort_by {|issue| ids.index(issue.id)}
289 end
289 end
290
290
291 # Return the columns that are displayed in the list
291 # Return the columns that are displayed in the list
292 def columns_in_issues_list
292 def columns_in_issues_list
293 css_select('table.issues thead th:not(.checkbox)').map(&:text)
293 css_select('table.issues thead th:not(.checkbox)').map(&:text)
294 end
294 end
295
295
296 # Verifies that the query filters match the expected filters
296 # Verifies that the query filters match the expected filters
297 def assert_query_filters(expected_filters)
297 def assert_query_filters(expected_filters)
298 response.body =~ /initFilters\(\);\s*((addFilter\(.+\);\s*)*)/
298 response.body =~ /initFilters\(\);\s*((addFilter\(.+\);\s*)*)/
299 filter_init = $1.to_s
299 filter_init = $1.to_s
300
300
301 expected_filters.each do |field, operator, values|
301 expected_filters.each do |field, operator, values|
302 s = "addFilter(#{field.to_json}, #{operator.to_json}, #{Array(values).to_json});"
302 s = "addFilter(#{field.to_json}, #{operator.to_json}, #{Array(values).to_json});"
303 assert_include s, filter_init
303 assert_include s, filter_init
304 end
304 end
305 assert_equal expected_filters.size, filter_init.scan("addFilter").size, "filters counts don't match"
305 assert_equal expected_filters.size, filter_init.scan("addFilter").size, "filters counts don't match"
306 end
306 end
307
307
308 def process(method, path, parameters={}, session={}, flash={})
308 def process(method, path, parameters={}, session={}, flash={})
309 if parameters.key?(:params) || parameters.key?(:session)
309 if parameters.key?(:params) || parameters.key?(:session)
310 raise ArgumentError if session.present?
310 raise ArgumentError if session.present?
311 super method, path, parameters[:params], parameters[:session], parameters.except(:params, :session)
311 super method, path, parameters[:params], parameters[:session], parameters.except(:params, :session)
312 else
312 else
313 super
313 super
314 end
314 end
315 end
315 end
316 end
316 end
317
317
318 class IntegrationTest < ActionDispatch::IntegrationTest
318 class IntegrationTest < ActionDispatch::IntegrationTest
319 def log_user(login, password)
319 def log_user(login, password)
320 User.anonymous
320 User.anonymous
321 get "/login"
321 get "/login"
322 assert_equal nil, session[:user_id]
322 assert_nil session[:user_id]
323 assert_response :success
323 assert_response :success
324
324
325 post "/login", :username => login, :password => password
325 post "/login", :username => login, :password => password
326 assert_equal login, User.find(session[:user_id]).login
326 assert_equal login, User.find(session[:user_id]).login
327 end
327 end
328
328
329 def credentials(user, password=nil)
329 def credentials(user, password=nil)
330 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
330 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
331 end
331 end
332 end
332 end
333
333
334 module ApiTest
334 module ApiTest
335 API_FORMATS = %w(json xml).freeze
335 API_FORMATS = %w(json xml).freeze
336
336
337 # Base class for API tests
337 # Base class for API tests
338 class Base < Redmine::IntegrationTest
338 class Base < Redmine::IntegrationTest
339 def setup
339 def setup
340 Setting.rest_api_enabled = '1'
340 Setting.rest_api_enabled = '1'
341 end
341 end
342
342
343 def teardown
343 def teardown
344 Setting.rest_api_enabled = '0'
344 Setting.rest_api_enabled = '0'
345 end
345 end
346
346
347 # Uploads content using the XML API and returns the attachment token
347 # Uploads content using the XML API and returns the attachment token
348 def xml_upload(content, credentials)
348 def xml_upload(content, credentials)
349 upload('xml', content, credentials)
349 upload('xml', content, credentials)
350 end
350 end
351
351
352 # Uploads content using the JSON API and returns the attachment token
352 # Uploads content using the JSON API and returns the attachment token
353 def json_upload(content, credentials)
353 def json_upload(content, credentials)
354 upload('json', content, credentials)
354 upload('json', content, credentials)
355 end
355 end
356
356
357 def upload(format, content, credentials)
357 def upload(format, content, credentials)
358 set_tmp_attachments_directory
358 set_tmp_attachments_directory
359 assert_difference 'Attachment.count' do
359 assert_difference 'Attachment.count' do
360 post "/uploads.#{format}", content, {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials)
360 post "/uploads.#{format}", content, {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials)
361 assert_response :created
361 assert_response :created
362 end
362 end
363 data = response_data
363 data = response_data
364 assert_kind_of Hash, data['upload']
364 assert_kind_of Hash, data['upload']
365 token = data['upload']['token']
365 token = data['upload']['token']
366 assert_not_nil token
366 assert_not_nil token
367 token
367 token
368 end
368 end
369
369
370 # Parses the response body based on its content type
370 # Parses the response body based on its content type
371 def response_data
371 def response_data
372 unless response.content_type.to_s =~ /^application\/(.+)/
372 unless response.content_type.to_s =~ /^application\/(.+)/
373 raise "Unexpected response type: #{response.content_type}"
373 raise "Unexpected response type: #{response.content_type}"
374 end
374 end
375 format = $1
375 format = $1
376 case format
376 case format
377 when 'xml'
377 when 'xml'
378 Hash.from_xml(response.body)
378 Hash.from_xml(response.body)
379 when 'json'
379 when 'json'
380 ActiveSupport::JSON.decode(response.body)
380 ActiveSupport::JSON.decode(response.body)
381 else
381 else
382 raise "Unknown response format: #{format}"
382 raise "Unknown response format: #{format}"
383 end
383 end
384 end
384 end
385 end
385 end
386
386
387 class Routing < Redmine::RoutingTest
387 class Routing < Redmine::RoutingTest
388 def should_route(arg)
388 def should_route(arg)
389 arg = arg.dup
389 arg = arg.dup
390 request = arg.keys.detect {|key| key.is_a?(String)}
390 request = arg.keys.detect {|key| key.is_a?(String)}
391 raise ArgumentError unless request
391 raise ArgumentError unless request
392 options = arg.slice!(request)
392 options = arg.slice!(request)
393
393
394 API_FORMATS.each do |format|
394 API_FORMATS.each do |format|
395 format_request = request.sub /$/, ".#{format}"
395 format_request = request.sub /$/, ".#{format}"
396 super options.merge(format_request => arg[request], :format => format)
396 super options.merge(format_request => arg[request], :format => format)
397 end
397 end
398 end
398 end
399 end
399 end
400 end
400 end
401 end
401 end
General Comments 0
You need to be logged in to leave comments. Login now