aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb43
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb8
-rw-r--r--actionpack/test/dispatch/request/multipart_params_parsing_test.rb21
-rw-r--r--actionpack/test/fixtures/multipart/bracketed_utf8_param5
-rw-r--r--actionpack/test/fixtures/multipart/single_utf8_param5
-rw-r--r--activerecord/CHANGELOG.md15
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb2
-rw-r--r--activerecord/lib/active_record/core.rb8
-rw-r--r--activerecord/lib/active_record/relation.rb8
-rw-r--r--activerecord/test/cases/associations_test.rb5
-rw-r--r--activerecord/test/cases/relations_test.rb10
12 files changed, 99 insertions, 35 deletions
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index f945a5c1a2..246d9c121a 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -18,7 +18,7 @@ module ActionDispatch
query_parameters.dup
end
params.merge!(path_parameters)
- encode_params(params).with_indifferent_access
+ params.with_indifferent_access
end
end
alias :params :parameters
@@ -50,40 +50,33 @@ module ActionDispatch
private
+ # Convert nested Hash to HashWithIndifferentAccess
+ # and UTF-8 encode both keys and values in nested Hash.
+ #
# TODO: Validate that the characters are UTF-8. If they aren't,
# you'll get a weird error down the road, but our form handling
# should really prevent that from happening
- def encode_params(params)
+ def normalize_encode_params(params)
if params.is_a?(String)
return params.force_encoding(Encoding::UTF_8).encode!
elsif !params.is_a?(Hash)
return params
end
- params.each_value do |v|
- case v
- when Hash
- encode_params(v)
- when Array
- v.map! {|el| encode_params(el) }
- else
- encode_params(v)
- end
- end
- end
-
- # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess
- def normalize_parameters(value)
- case value
- when Hash
- h = {}
- value.each { |k, v| h[k] = normalize_parameters(v) }
- h.with_indifferent_access
- when Array
- value.map { |e| normalize_parameters(e) }
- else
- value
+ new_hash = {}
+ params.each do |k, v|
+ new_key = k.is_a?(String) ? k.dup.force_encoding("UTF-8").encode! : k
+ new_hash[new_key] =
+ case v
+ when Hash
+ normalize_encode_params(v)
+ when Array
+ v.map! {|el| normalize_encode_params(el) }
+ else
+ normalize_encode_params(v)
+ end
end
+ new_hash.with_indifferent_access
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 97a9b7be86..aff2172788 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -273,7 +273,7 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
- @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
+ @env["action_dispatch.request.query_parameters"] ||= (normalize_encode_params(super) || {})
rescue TypeError => e
raise ActionController::BadRequest.new(:query, e)
end
@@ -281,7 +281,7 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
- @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
+ @env["action_dispatch.request.request_parameters"] ||= (normalize_encode_params(super) || {})
rescue TypeError => e
raise ActionController::BadRequest.new(:request, e)
end
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 67cb7fbcb5..319d0197d1 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -75,16 +75,16 @@ module ActionDispatch
end
module Upload # :nodoc:
- # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess and replace
- # file upload hash with UploadedFile objects
- def normalize_parameters(value)
+ # Replace file upload hash with UploadedFile objects
+ # when normalize and encode parameters.
+ def normalize_encode_params(value)
if Hash === value && value.has_key?(:tempfile)
UploadedFile.new(value)
else
super
end
end
- private :normalize_parameters
+ private :normalize_encode_params
end
end
end
diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
index 399f15199c..3c30a705e9 100644
--- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
@@ -1,13 +1,15 @@
+# encoding: utf-8
require 'abstract_unit'
class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
class TestController < ActionController::Base
class << self
- attr_accessor :last_request_parameters
+ attr_accessor :last_request_parameters, :last_parameters
end
def parse
self.class.last_request_parameters = request.request_parameters
+ self.class.last_parameters = request.parameters
head :ok
end
@@ -30,6 +32,23 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
assert_equal({ 'foo' => { 'baz' => 'bar'}}, parse_multipart('bracketed_param'))
end
+ test "parse single utf8 parameter" do
+ assert_equal({ 'Iñtërnâtiônàlizætiøn_name' => 'Iñtërnâtiônàlizætiøn_value'},
+ parse_multipart('single_utf8_param'), "request.request_parameters")
+ assert_equal(
+ 'Iñtërnâtiônàlizætiøn_value',
+ TestController.last_parameters['Iñtërnâtiônàlizætiøn_name'], "request.parameters")
+ end
+
+ test "parse bracketed utf8 parameter" do
+ assert_equal({ 'Iñtërnâtiônàlizætiøn_name' => {
+ 'Iñtërnâtiônàlizætiøn_nested_name' => 'Iñtërnâtiônàlizætiøn_value'} },
+ parse_multipart('bracketed_utf8_param'), "request.request_parameters")
+ assert_equal(
+ {'Iñtërnâtiônàlizætiøn_nested_name' => 'Iñtërnâtiônàlizætiøn_value'},
+ TestController.last_parameters['Iñtërnâtiônàlizætiøn_name'], "request.parameters")
+ end
+
test "parses text file" do
params = parse_multipart('text_file')
assert_equal %w(file foo), params.keys.sort
diff --git a/actionpack/test/fixtures/multipart/bracketed_utf8_param b/actionpack/test/fixtures/multipart/bracketed_utf8_param
new file mode 100644
index 0000000000..976ca44a45
--- /dev/null
+++ b/actionpack/test/fixtures/multipart/bracketed_utf8_param
@@ -0,0 +1,5 @@
+--AaB03x
+Content-Disposition: form-data; name="Iñtërnâtiônàlizætiøn_name[Iñtërnâtiônàlizætiøn_nested_name]"
+
+Iñtërnâtiônàlizætiøn_value
+--AaB03x--
diff --git a/actionpack/test/fixtures/multipart/single_utf8_param b/actionpack/test/fixtures/multipart/single_utf8_param
new file mode 100644
index 0000000000..b86f62d1e1
--- /dev/null
+++ b/actionpack/test/fixtures/multipart/single_utf8_param
@@ -0,0 +1,5 @@
+--AaB03x
+Content-Disposition: form-data; name="Iñtërnâtiônàlizætiøn_name"
+
+Iñtërnâtiônàlizætiøn_value
+--AaB03x--
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 6affb2aada..a8151cd23e 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,20 @@
## Rails 4.0.0 (unreleased) ##
+* Referencing join tables implicitly was deprecated. There is a
+ possibility that these deprecation warnings are shown even if you
+ don't make use of that feature. You can now disable the feature entirely.
+ Fixes #9712.
+
+ Example:
+
+ # in your configuration
+ config.active_record.disable_implicit_join_references = true
+
+ # or directly
+ ActiveRecord::Base.disable_implicit_join_references = true
+
+ *Yves Senn*
+
* The `:distinct` option for `Relation#count` is deprecated. You
should use `Relation#distinct` instead.
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 18b7dc3668..906560bd44 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -34,7 +34,7 @@ module ActiveRecord
reload
end
- CollectionProxy.new(klass, self)
+ @proxy ||= CollectionProxy.new(klass, self)
end
# Implements the writer method, e.g. foo.items= for Foo.has_many :items
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 72371be657..aa56219755 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -69,6 +69,14 @@ module ActiveRecord
mattr_accessor :timestamped_migrations, instance_writer: false
self.timestamped_migrations = true
+ ##
+ # :singleton-method:
+ # Disable implicit join references. This feature was deprecated with Rails 4.
+ # If you don't make use of implicit references but still see deprecation warnings
+ # you can disable the feature entirely. This will be the default with Rails 4.1.
+ mattr_accessor :disable_implicit_join_references, instance_writer: false
+ self.disable_implicit_join_references = false
+
class_attribute :connection_handler, instance_writer: false
self.connection_handler = ConnectionAdapters::ConnectionHandler.new
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 50723b4848..037097d2dd 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -595,7 +595,8 @@ module ActiveRecord
if (references_values - joined_tables).any?
true
- elsif (string_tables - joined_tables).any?
+ elsif !ActiveRecord::Base.disable_implicit_join_references &&
+ (string_tables - joined_tables).any?
ActiveSupport::Deprecation.warn(
"It looks like you are eager loading table(s) (one of: #{string_tables.join(', ')}) " \
"that are referenced in a string SQL snippet. For example: \n" \
@@ -609,7 +610,10 @@ module ActiveRecord
"From now on, you must explicitly tell Active Record when you are referencing a table " \
"from a string:\n" \
"\n" \
- " Post.includes(:comments).where(\"comments.title = 'foo'\").references(:comments)\n\n"
+ " Post.includes(:comments).where(\"comments.title = 'foo'\").references(:comments)\n" \
+ "\n" \
+ "If you don't rely on implicit join references you can disable the feature entirely" \
+ "by setting `config.active_record.disable_implicit_join_references = true`."
)
true
else
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 41529cd050..a06bacafca 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -237,6 +237,11 @@ class AssociationProxyTest < ActiveRecord::TestCase
assert david.projects.scope.is_a?(ActiveRecord::Relation)
assert_equal david.projects, david.projects.scope
end
+
+ test "proxy object is cached" do
+ david = developers(:david)
+ assert david.projects.equal?(david.projects)
+ end
end
class OverridingAssociationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index db81ceeb52..9008c2785e 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1224,6 +1224,16 @@ class RelationTest < ActiveRecord::TestCase
end
end
+ def test_turn_off_eager_loading_with_conditions_on_joins
+ original_value = ActiveRecord::Base.disable_implicit_join_references
+ ActiveRecord::Base.disable_implicit_join_references = true
+
+ scope = Topic.where(author_email_address: 'my.example@gmail.com').includes(:replies)
+ assert_not scope.eager_loading?
+ ensure
+ ActiveRecord::Base.disable_implicit_join_references = original_value
+ end
+
def test_ordering_with_extra_spaces
assert_equal authors(:david), Author.order('id DESC , name DESC').last
end