rack-test 0.6.3 → 0.8.3

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.
@@ -1,16 +1,15 @@
1
- require "tempfile"
2
- require "fileutils"
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'tempfile'
3
4
 
4
5
  module Rack
5
6
  module Test
6
-
7
7
  # Wraps a Tempfile with a content type. Including one or more UploadedFile's
8
8
  # in the params causes Rack::Test to build and issue a multipart request.
9
9
  #
10
10
  # Example:
11
11
  # post "/photos", "file" => Rack::Test::UploadedFile.new("me.jpg", "image/jpeg")
12
12
  class UploadedFile
13
-
14
13
  # The filename, *not* including the path, of the "uploaded" file
15
14
  attr_reader :original_filename
16
15
 
@@ -20,34 +19,66 @@ module Rack
20
19
  # The content type of the "uploaded" file
21
20
  attr_accessor :content_type
22
21
 
23
- def initialize(path, content_type = "text/plain", binary = false)
24
- raise "#{path} file does not exist" unless ::File.exist?(path)
25
-
22
+ # Creates a new UploadedFile instance.
23
+ #
24
+ # @param content [IO, Pathname, String, StringIO] a path to a file, or an {IO} or {StringIO} object representing the
25
+ # file.
26
+ # @param content_type [String]
27
+ # @param binary [Boolean] an optional flag that indicates whether the file should be open in binary mode or not.
28
+ # @param original_filename [String] an optional parameter that provides the original filename if `content` is a StringIO
29
+ # object. Not used for other kind of `content` objects.
30
+ def initialize(content, content_type = 'text/plain', binary = false, original_filename: nil)
31
+ if original_filename
32
+ initialize_from_stringio(content, original_filename)
33
+ else
34
+ initialize_from_file_path(content)
35
+ end
26
36
  @content_type = content_type
27
- @original_filename = ::File.basename(path)
28
-
29
- @tempfile = Tempfile.new(@original_filename)
30
- @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
31
37
  @tempfile.binmode if binary
32
-
33
- FileUtils.copy_file(path, @tempfile.path)
34
38
  end
35
39
 
36
40
  def path
37
- @tempfile.path
41
+ tempfile.path
38
42
  end
39
43
 
40
- alias_method :local_path, :path
44
+ alias local_path path
41
45
 
42
46
  def method_missing(method_name, *args, &block) #:nodoc:
43
- @tempfile.__send__(method_name, *args, &block)
47
+ tempfile.public_send(method_name, *args, &block)
44
48
  end
45
49
 
46
- def respond_to?(method_name, include_private = false) #:nodoc:
47
- @tempfile.respond_to?(method_name, include_private) || super
50
+ def respond_to_missing?(method_name, include_private = false) #:nodoc:
51
+ tempfile.respond_to?(method_name, include_private) || super
48
52
  end
49
53
 
50
- end
54
+ def self.finalize(file)
55
+ proc { actually_finalize file }
56
+ end
57
+
58
+ def self.actually_finalize(file)
59
+ file.close
60
+ file.unlink
61
+ end
51
62
 
63
+ private
64
+
65
+ def initialize_from_stringio(stringio, original_filename)
66
+ @tempfile = stringio
67
+ @original_filename = original_filename || raise(ArgumentError, 'Missing `original_filename` for StringIO object')
68
+ end
69
+
70
+ def initialize_from_file_path(path)
71
+ raise "#{path} file does not exist" unless ::File.exist?(path)
72
+
73
+ @original_filename = ::File.basename(path)
74
+
75
+ @tempfile = Tempfile.new([@original_filename, ::File.extname(path)])
76
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
77
+
78
+ ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))
79
+
80
+ FileUtils.copy_file(path, @tempfile.path)
81
+ end
82
+ end
52
83
  end
53
84
  end
@@ -1,38 +1,36 @@
1
1
  module Rack
2
2
  module Test
3
-
4
3
  module Utils # :nodoc:
5
4
  include Rack::Utils
5
+ extend Rack::Utils
6
6
 
7
7
  def build_nested_query(value, prefix = nil)
8
8
  case value
9
9
  when Array
10
- value.map do |v|
11
- unless unescape(prefix) =~ /\[\]$/
12
- prefix = "#{prefix}[]"
13
- end
14
- build_nested_query(v, "#{prefix}")
15
- end.join("&")
10
+ if value.empty?
11
+ "#{prefix}[]="
12
+ else
13
+ value.map do |v|
14
+ prefix = "#{prefix}[]" unless unescape(prefix) =~ /\[\]$/
15
+ build_nested_query(v, prefix.to_s)
16
+ end.join('&')
17
+ end
16
18
  when Hash
17
19
  value.map do |k, v|
18
20
  build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
19
- end.join("&")
21
+ end.join('&')
20
22
  when NilClass
21
23
  prefix.to_s
22
24
  else
23
25
  "#{prefix}=#{escape(value)}"
24
26
  end
25
27
  end
26
-
27
28
  module_function :build_nested_query
28
29
 
29
- def build_multipart(params, first = true)
30
+ def build_multipart(params, first = true, multipart = false)
30
31
  if first
31
- unless params.is_a?(Hash)
32
- raise ArgumentError, "value must be a Hash"
33
- end
32
+ raise ArgumentError, 'value must be a Hash' unless params.is_a?(Hash)
34
33
 
35
- multipart = false
36
34
  query = lambda { |value|
37
35
  case value
38
36
  when Array
@@ -47,7 +45,7 @@ module Rack
47
45
  return nil unless multipart
48
46
  end
49
47
 
50
- flattened_params = Hash.new
48
+ flattened_params = {}
51
49
 
52
50
  params.each do |key, value|
53
51
  k = first ? key.to_s : "[#{key}]"
@@ -55,23 +53,21 @@ module Rack
55
53
  case value
56
54
  when Array
57
55
  value.map do |v|
58
-
59
- if (v.is_a?(Hash))
56
+ if v.is_a?(Hash)
60
57
  nested_params = {}
61
- build_multipart(v, false).each { |subkey, subvalue|
58
+ build_multipart(v, false).each do |subkey, subvalue|
62
59
  nested_params[subkey] = subvalue
63
- }
60
+ end
64
61
  flattened_params["#{k}[]"] ||= []
65
62
  flattened_params["#{k}[]"] << nested_params
66
63
  else
67
64
  flattened_params["#{k}[]"] = value
68
65
  end
69
-
70
66
  end
71
67
  when Hash
72
- build_multipart(value, false).each { |subkey, subvalue|
68
+ build_multipart(value, false).each do |subkey, subvalue|
73
69
  flattened_params[k + subkey] = subvalue
74
- }
70
+ end
75
71
  else
76
72
  flattened_params[k] = value
77
73
  end
@@ -83,27 +79,28 @@ module Rack
83
79
  flattened_params
84
80
  end
85
81
  end
86
-
87
82
  module_function :build_multipart
88
83
 
89
- private
84
+ private
85
+
90
86
  def build_parts(parameters)
91
87
  get_parts(parameters).join + "--#{MULTIPART_BOUNDARY}--\r"
92
88
  end
89
+ module_function :build_parts
93
90
 
94
91
  def get_parts(parameters)
95
- parameters.map { |name, value|
96
- if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? {|v| v.is_a?(Hash)}
97
- value.map { |hash|
92
+ parameters.map do |name, value|
93
+ if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? { |v| v.is_a?(Hash) }
94
+ value.map do |hash|
98
95
  new_value = {}
99
- hash.each { |k, v| new_value[name+k] = v }
96
+ hash.each { |k, v| new_value[name + k] = v }
100
97
  get_parts(new_value).join
101
- }.join
98
+ end.join
102
99
  else
103
100
  if value.respond_to?(:original_filename)
104
101
  build_file_part(name, value)
105
102
 
106
- elsif value.is_a?(Array) and value.all? { |v| v.respond_to?(:original_filename) }
103
+ elsif value.is_a?(Array) && value.all? { |v| v.respond_to?(:original_filename) }
107
104
  value.map do |v|
108
105
  build_file_part(name, v)
109
106
  end.join
@@ -113,15 +110,14 @@ module Rack
113
110
  Rack::Test.encoding_aware_strings? ? primitive_part.force_encoding('BINARY') : primitive_part
114
111
  end
115
112
  end
116
- }
113
+ end
117
114
  end
115
+ module_function :get_parts
118
116
 
119
117
  def build_primitive_part(parameter_name, value)
120
- unless value.is_a? Array
121
- value = [value]
122
- end
118
+ value = [value] unless value.is_a? Array
123
119
  value.map do |v|
124
- <<-EOF
120
+ <<-EOF
125
121
  --#{MULTIPART_BOUNDARY}\r
126
122
  Content-Disposition: form-data; name="#{parameter_name}"\r
127
123
  \r
@@ -129,22 +125,20 @@ Content-Disposition: form-data; name="#{parameter_name}"\r
129
125
  EOF
130
126
  end.join
131
127
  end
128
+ module_function :build_primitive_part
132
129
 
133
130
  def build_file_part(parameter_name, uploaded_file)
134
- ::File.open(uploaded_file.path, "rb") do |physical_file|
135
- physical_file.set_encoding(Encoding::BINARY) if physical_file.respond_to?(:set_encoding)
136
- <<-EOF
131
+ uploaded_file.set_encoding(Encoding::BINARY) if uploaded_file.respond_to?(:set_encoding)
132
+ <<-EOF
137
133
  --#{MULTIPART_BOUNDARY}\r
138
134
  Content-Disposition: form-data; name="#{parameter_name}"; filename="#{escape(uploaded_file.original_filename)}"\r
139
135
  Content-Type: #{uploaded_file.content_type}\r
140
- Content-Length: #{::File.stat(uploaded_file.path).size}\r
136
+ Content-Length: #{uploaded_file.size}\r
141
137
  \r
142
- #{physical_file.read}\r
138
+ #{uploaded_file.read}\r
143
139
  EOF
144
- end
145
140
  end
146
-
141
+ module_function :build_file_part
147
142
  end
148
-
149
143
  end
150
144
  end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ module Test
3
+ VERSION = '0.8.3'.freeze
4
+ end
5
+ end
data/lib/rack/test.rb CHANGED
@@ -1,18 +1,17 @@
1
- require "uri"
2
- require "rack"
3
- require "rack/mock_session"
4
- require "rack/test/cookie_jar"
5
- require "rack/test/mock_digest_request"
6
- require "rack/test/utils"
7
- require "rack/test/methods"
8
- require "rack/test/uploaded_file"
1
+ require 'uri'
2
+ require 'rack'
3
+ require 'rack/mock_session'
4
+ require 'rack/test/cookie_jar'
5
+ require 'rack/test/mock_digest_request'
6
+ require 'rack/test/utils'
7
+ require 'rack/test/methods'
8
+ require 'rack/test/uploaded_file'
9
+ require 'rack/test/version'
9
10
 
10
11
  module Rack
11
12
  module Test
12
- VERSION = "0.6.3"
13
-
14
- DEFAULT_HOST = "example.org"
15
- MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
13
+ DEFAULT_HOST = 'example.org'.freeze
14
+ MULTIPART_BOUNDARY = '----------XnJLe9ZIbbGUYtzPQJ16u1'.freeze
16
15
 
17
16
  # The common base class for exceptions raised by Rack::Test
18
17
  class Error < StandardError; end
@@ -36,11 +35,13 @@ module Rack
36
35
  def initialize(mock_session)
37
36
  @headers = {}
38
37
  @env = {}
38
+ @digest_username = nil
39
+ @digest_password = nil
39
40
 
40
- if mock_session.is_a?(MockSession)
41
- @rack_mock_session = mock_session
41
+ @rack_mock_session = if mock_session.is_a?(MockSession)
42
+ mock_session
42
43
  else
43
- @rack_mock_session = MockSession.new(mock_session)
44
+ MockSession.new(mock_session)
44
45
  end
45
46
 
46
47
  @default_host = @rack_mock_session.default_host
@@ -54,8 +55,7 @@ module Rack
54
55
  # Example:
55
56
  # get "/"
56
57
  def get(uri, params = {}, env = {}, &block)
57
- env = env_for(uri, env.merge(:method => "GET", :params => params))
58
- process_request(uri, env, &block)
58
+ custom_request('GET', uri, params, env, &block)
59
59
  end
60
60
 
61
61
  # Issue a POST request for the given URI. See #get
@@ -63,8 +63,7 @@ module Rack
63
63
  # Example:
64
64
  # post "/signup", "name" => "Bryan"
65
65
  def post(uri, params = {}, env = {}, &block)
66
- env = env_for(uri, env.merge(:method => "POST", :params => params))
67
- process_request(uri, env, &block)
66
+ custom_request('POST', uri, params, env, &block)
68
67
  end
69
68
 
70
69
  # Issue a PUT request for the given URI. See #get
@@ -72,8 +71,7 @@ module Rack
72
71
  # Example:
73
72
  # put "/"
74
73
  def put(uri, params = {}, env = {}, &block)
75
- env = env_for(uri, env.merge(:method => "PUT", :params => params))
76
- process_request(uri, env, &block)
74
+ custom_request('PUT', uri, params, env, &block)
77
75
  end
78
76
 
79
77
  # Issue a PATCH request for the given URI. See #get
@@ -81,8 +79,7 @@ module Rack
81
79
  # Example:
82
80
  # patch "/"
83
81
  def patch(uri, params = {}, env = {}, &block)
84
- env = env_for(uri, env.merge(:method => "PATCH", :params => params))
85
- process_request(uri, env, &block)
82
+ custom_request('PATCH', uri, params, env, &block)
86
83
  end
87
84
 
88
85
  # Issue a DELETE request for the given URI. See #get
@@ -90,8 +87,7 @@ module Rack
90
87
  # Example:
91
88
  # delete "/"
92
89
  def delete(uri, params = {}, env = {}, &block)
93
- env = env_for(uri, env.merge(:method => "DELETE", :params => params))
94
- process_request(uri, env, &block)
90
+ custom_request('DELETE', uri, params, env, &block)
95
91
  end
96
92
 
97
93
  # Issue an OPTIONS request for the given URI. See #get
@@ -99,8 +95,7 @@ module Rack
99
95
  # Example:
100
96
  # options "/"
101
97
  def options(uri, params = {}, env = {}, &block)
102
- env = env_for(uri, env.merge(:method => "OPTIONS", :params => params))
103
- process_request(uri, env, &block)
98
+ custom_request('OPTIONS', uri, params, env, &block)
104
99
  end
105
100
 
106
101
  # Issue a HEAD request for the given URI. See #get
@@ -108,8 +103,7 @@ module Rack
108
103
  # Example:
109
104
  # head "/"
110
105
  def head(uri, params = {}, env = {}, &block)
111
- env = env_for(uri, env.merge(:method => "HEAD", :params => params))
112
- process_request(uri, env, &block)
106
+ custom_request('HEAD', uri, params, env, &block)
113
107
  end
114
108
 
115
109
  # Issue a request to the Rack app for the given URI and optional Rack
@@ -120,10 +114,21 @@ module Rack
120
114
  # Example:
121
115
  # request "/"
122
116
  def request(uri, env = {}, &block)
117
+ uri = parse_uri(uri, env)
123
118
  env = env_for(uri, env)
124
119
  process_request(uri, env, &block)
125
120
  end
126
121
 
122
+ # Issue a request using the given verb for the given URI. See #get
123
+ #
124
+ # Example:
125
+ # custom_request "LINK", "/"
126
+ def custom_request(verb, uri, params = {}, env = {}, &block)
127
+ uri = parse_uri(uri, env)
128
+ env = env_for(uri, env.merge(method: verb.to_s.upcase, params: params))
129
+ process_request(uri, env, &block)
130
+ end
131
+
127
132
  # Set a header to be included on all subsequent requests through the
128
133
  # session. Use a value of nil to remove a previously configured header.
129
134
  #
@@ -159,11 +164,11 @@ module Rack
159
164
  # Example:
160
165
  # basic_authorize "bryan", "secret"
161
166
  def basic_authorize(username, password)
162
- encoded_login = ["#{username}:#{password}"].pack("m*")
167
+ encoded_login = ["#{username}:#{password}"].pack('m0')
163
168
  header('Authorization', "Basic #{encoded_login}")
164
169
  end
165
170
 
166
- alias_method :authorize, :basic_authorize
171
+ alias authorize basic_authorize
167
172
 
168
173
  # Set the username and password for HTTP Digest authorization, to be
169
174
  # included in subsequent requests in the HTTP_AUTHORIZATION header.
@@ -181,73 +186,73 @@ module Rack
181
186
  # a redirect, an error will be raised.
182
187
  def follow_redirect!
183
188
  unless last_response.redirect?
184
- raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
189
+ raise Error, 'Last response was not a redirect. Cannot follow_redirect!'
190
+ end
191
+ if last_response.status == 307
192
+ send(last_request.request_method.downcase.to_sym, last_response['Location'], last_request.params, 'HTTP_REFERER' => last_request.url)
193
+ else
194
+ get(last_response['Location'], {}, 'HTTP_REFERER' => last_request.url)
185
195
  end
186
-
187
- get(last_response["Location"], {}, { "HTTP_REFERER" => last_request.url })
188
196
  end
189
197
 
190
- private
198
+ private
191
199
 
192
- def env_for(path, env)
193
- uri = URI.parse(path)
194
- uri.path = "/#{uri.path}" unless uri.path[0] == ?/
195
- uri.host ||= @default_host
200
+ def parse_uri(path, env)
201
+ URI.parse(path).tap do |uri|
202
+ uri.path = "/#{uri.path}" unless uri.path[0] == '/'
203
+ uri.host ||= @default_host
204
+ uri.scheme ||= 'https' if env['HTTPS'] == 'on'
205
+ end
206
+ end
196
207
 
208
+ def env_for(uri, env)
197
209
  env = default_env.merge(env)
198
210
 
199
- env["HTTP_HOST"] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(":")
211
+ env['HTTP_HOST'] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(':')
200
212
 
201
- env.update("HTTPS" => "on") if URI::HTTPS === uri
202
- env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" if env[:xhr]
213
+ env.update('HTTPS' => 'on') if URI::HTTPS === uri
214
+ env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if env[:xhr]
203
215
 
204
216
  # TODO: Remove this after Rack 1.1 has been released.
205
217
  # Stringifying and upcasing methods has be commit upstream
206
- env["REQUEST_METHOD"] ||= env[:method] ? env[:method].to_s.upcase : "GET"
218
+ env['REQUEST_METHOD'] ||= env[:method] ? env[:method].to_s.upcase : 'GET'
219
+
220
+ params = env.delete(:params) do {} end
207
221
 
208
- if env["REQUEST_METHOD"] == "GET"
222
+ if env['REQUEST_METHOD'] == 'GET'
209
223
  # merge :params with the query string
210
- if params = env[:params]
224
+ if params
211
225
  params = parse_nested_query(params) if params.is_a?(String)
212
- params.update(parse_nested_query(uri.query))
213
- uri.query = build_nested_query(params)
226
+
227
+ uri.query = [uri.query, build_nested_query(params)].compact.reject { |v| v == '' }.join('&')
214
228
  end
215
- elsif !env.has_key?(:input)
216
- env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded"
229
+ elsif !env.key?(:input)
230
+ env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded' unless params.nil?
217
231
 
218
- if env[:params].is_a?(Hash)
219
- if data = build_multipart(env[:params])
232
+ if params.is_a?(Hash)
233
+ if data = build_multipart(params)
220
234
  env[:input] = data
221
- env["CONTENT_LENGTH"] ||= data.length.to_s
222
- env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
235
+ env['CONTENT_LENGTH'] ||= data.length.to_s
236
+ env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
223
237
  else
224
- env[:input] = params_to_string(env[:params])
238
+ env[:input] = params_to_string(params)
225
239
  end
226
240
  else
227
- env[:input] = env[:params]
241
+ env[:input] = params
228
242
  end
229
243
  end
230
244
 
231
- env.delete(:params)
232
-
233
- if env.has_key?(:cookie)
234
- set_cookie(env.delete(:cookie), uri)
235
- end
245
+ set_cookie(env.delete(:cookie), uri) if env.key?(:cookie)
236
246
 
237
247
  Rack::MockRequest.env_for(uri.to_s, env)
238
248
  end
239
249
 
240
250
  def process_request(uri, env)
241
- uri = URI.parse(uri)
242
- uri.host ||= @default_host
243
-
244
251
  @rack_mock_session.request(uri, env)
245
252
 
246
253
  if retry_with_digest_auth?(env)
247
- auth_env = env.merge({
248
- "HTTP_AUTHORIZATION" => digest_auth_header,
249
- "rack-test.digest_auth_retry" => true
250
- })
254
+ auth_env = env.merge('HTTP_AUTHORIZATION' => digest_auth_header,
255
+ 'rack-test.digest_auth_retry' => true)
251
256
  auth_env.delete('rack.request')
252
257
  process_request(uri.path, auth_env)
253
258
  else
@@ -258,26 +263,24 @@ module Rack
258
263
  end
259
264
 
260
265
  def digest_auth_header
261
- challenge = last_response["WWW-Authenticate"].split(" ", 2).last
266
+ challenge = last_response['WWW-Authenticate'].split(' ', 2).last
262
267
  params = Rack::Auth::Digest::Params.parse(challenge)
263
268
 
264
- params.merge!({
265
- "username" => @digest_username,
266
- "nc" => "00000001",
267
- "cnonce" => "nonsensenonce",
268
- "uri" => last_request.fullpath,
269
- "method" => last_request.env["REQUEST_METHOD"],
270
- })
269
+ params.merge!('username' => @digest_username,
270
+ 'nc' => '00000001',
271
+ 'cnonce' => 'nonsensenonce',
272
+ 'uri' => last_request.fullpath,
273
+ 'method' => last_request.env['REQUEST_METHOD'])
271
274
 
272
- params["response"] = MockDigestRequest.new(params).response(@digest_password)
275
+ params['response'] = MockDigestRequest.new(params).response(@digest_password)
273
276
 
274
277
  "Digest #{params}"
275
278
  end
276
279
 
277
280
  def retry_with_digest_auth?(env)
278
281
  last_response.status == 401 &&
279
- digest_auth_configured? &&
280
- !env["rack-test.digest_auth_retry"]
282
+ digest_auth_configured? &&
283
+ !env['rack-test.digest_auth_retry']
281
284
  end
282
285
 
283
286
  def digest_auth_configured?
@@ -285,15 +288,15 @@ module Rack
285
288
  end
286
289
 
287
290
  def default_env
288
- { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@env).merge(headers_for_env)
291
+ { 'rack.test' => true, 'REMOTE_ADDR' => '127.0.0.1' }.merge(@env).merge(headers_for_env)
289
292
  end
290
293
 
291
294
  def headers_for_env
292
295
  converted_headers = {}
293
296
 
294
297
  @headers.each do |name, value|
295
- env_key = name.upcase.gsub("-", "_")
296
- env_key = "HTTP_" + env_key unless "CONTENT_TYPE" == env_key
298
+ env_key = name.upcase.tr('-', '_')
299
+ env_key = 'HTTP_' + env_key unless env_key == 'CONTENT_TYPE'
297
300
  converted_headers[env_key] = value
298
301
  end
299
302
 
@@ -303,16 +306,14 @@ module Rack
303
306
  def params_to_string(params)
304
307
  case params
305
308
  when Hash then build_nested_query(params)
306
- when nil then ""
309
+ when nil then ''
307
310
  else params
308
311
  end
309
312
  end
310
-
311
313
  end
312
314
 
313
315
  def self.encoding_aware_strings?
314
- defined?(Encoding) && "".respond_to?(:encode)
316
+ defined?(Encoding) && ''.respond_to?(:encode)
315
317
  end
316
-
317
318
  end
318
319
  end