diff options
Diffstat (limited to 'activerecord')
10 files changed, 129 insertions, 6 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 34603b7f23..936dcbb2fb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,25 @@ +* `type_to_sql` returns a `String` for unmapped columns. This fixes an error + when using unmapped array types in PG + + Example: + + change_colum :table, :column, :bigint, array: true + + Fixes #13146. + + *Jens Fahnenbruck*, *Yves Senn* + +* Fix `QueryCache` to work with nested blocks, so that it will only clear the existing cache + after leaving the outer block instead of clearing it right after the inner block is finished. + + *Vipul A M* + +* The ERB in fixture files is no longer evaluated in the context of the main + object. Helper methods used by multiple fixtures should be defined on the + class object returned by `ActiveRecord::FixtureSet.context_class`. + + *Victor Costan* + * Previously, the `has_one` macro incorrectly accepted the `counter_cache` option, but never actually supported it. Now it will raise an `ArgumentError` when using `has_one` with `counter_cache`. diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 128a9377c1..35f19f0bc0 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -128,7 +128,7 @@ module ActiveRecord # record.credit_card_number = decrypt(record.credit_card_number) # end # - # alias_method :after_find, :after_save + # alias_method :after_initialize, :after_save # # private # def encrypt(value) @@ -163,7 +163,7 @@ module ActiveRecord # record.send("#{@attribute}=", decrypt(record.send("#{@attribute}"))) # end # - # alias_method :after_find, :after_save + # alias_method :after_initialize, :after_save # # private # def encrypt(value) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index 8399232d73..adc23a6674 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -31,8 +31,8 @@ module ActiveRecord old, @query_cache_enabled = @query_cache_enabled, true yield ensure - clear_query_cache @query_cache_enabled = old + clear_query_cache unless @query_cache_enabled end def enable_query_cache! diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 6268ae4875..51a6929dab 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -690,7 +690,7 @@ module ActiveRecord column_type_sql else - type + type.to_s end end diff --git a/activerecord/lib/active_record/fixture_set/file.rb b/activerecord/lib/active_record/fixture_set/file.rb index fbd7a4d891..8132310c91 100644 --- a/activerecord/lib/active_record/fixture_set/file.rb +++ b/activerecord/lib/active_record/fixture_set/file.rb @@ -38,7 +38,8 @@ module ActiveRecord end def render(content) - ERB.new(content).result + context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new + ERB.new(content).result(context.get_binding) end # Validate our unmarshalled data. diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 8601414209..d241788a9b 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -119,6 +119,23 @@ module ActiveRecord # perhaps you should reexamine whether your application is properly testable. Hence, dynamic values # in fixtures are to be considered a code smell. # + # Helper methods defined in a fixture will not be available in other fixtures, to prevent against + # unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module + # that is included in <tt>ActiveRecord::FixtureSet.context_class</tt>. + # + # - define a helper method in `test_helper.rb` + # class FixtureFileHelpers + # def file_sha(path) + # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path))) + # end + # end + # ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers + # + # - use the helper method in a fixture + # photo: + # name: kitten.png + # sha: <%= file_sha 'files/kitten.png' %> + # # = Transactional Fixtures # # Test cases can use begin+rollback to isolate their changes to the database instead of having to @@ -529,6 +546,11 @@ module ActiveRecord Zlib.crc32(label.to_s) % MAX_ID end + # Superclass for the evaluation contexts used by ERB fixtures. + def self.context_class + @context_class ||= Class.new + end + attr_reader :table_name, :name, :fixtures, :model_class, :config def initialize(connection, name, class_name, path, config = ActiveRecord::Base) @@ -989,3 +1011,13 @@ module ActiveRecord end end end + +class ActiveRecord::FixtureSet::RenderContext # :nodoc: + def self.create_subclass + Class.new ActiveRecord::FixtureSet.context_class do + def get_binding + binding() + end + end + end +end diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 595edc6263..34be68a97f 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -178,6 +178,10 @@ module ActiveRecord result = @connection.select_all "SELECT * FROM posts" assert result.is_a?(ActiveRecord::Result) end + + test "type_to_sql returns a String for unmapped types" do + assert_equal "special_db_type", @connection.type_to_sql(:special_db_type) + end end class AdapterTestWithoutTransaction < ActiveRecord::TestCase diff --git a/activerecord/test/cases/fixture_set/file_test.rb b/activerecord/test/cases/fixture_set/file_test.rb index a029fedbd3..92efa8aca7 100644 --- a/activerecord/test/cases/fixture_set/file_test.rb +++ b/activerecord/test/cases/fixture_set/file_test.rb @@ -68,6 +68,61 @@ module ActiveRecord end end + def test_render_context_helper + ActiveRecord::FixtureSet.context_class.class_eval do + def fixture_helper + "Fixture helper" + end + end + yaml = "one:\n name: <%= fixture_helper %>\n" + tmp_yaml ['curious', 'yml'], yaml do |t| + golden = + [["one", {"name" => "Fixture helper"}]] + assert_equal golden, File.open(t.path) { |fh| fh.to_a } + end + ActiveRecord::FixtureSet.context_class.class_eval do + remove_method :fixture_helper + end + end + + def test_render_context_lookup_scope + yaml = <<END +one: + ActiveRecord: <%= defined? ActiveRecord %> + ActiveRecord_FixtureSet: <%= defined? ActiveRecord::FixtureSet %> + FixtureSet: <%= defined? FixtureSet %> + ActiveRecord_FixtureSet_File: <%= defined? ActiveRecord::FixtureSet::File %> + File: <%= File.name %> +END + + golden = [['one', { + 'ActiveRecord' => 'constant', + 'ActiveRecord_FixtureSet' => 'constant', + 'FixtureSet' => nil, + 'ActiveRecord_FixtureSet_File' => 'constant', + 'File' => 'File' + }]] + + tmp_yaml ['curious', 'yml'], yaml do |t| + assert_equal golden, File.open(t.path) { |fh| fh.to_a } + end + end + + # Make sure that each fixture gets its own rendering context so that + # fixtures are independent. + def test_independent_render_contexts + yaml1 = "<% def leaked_method; 'leak'; end %>\n" + yaml2 = "one:\n name: <%= leaked_method %>\n" + tmp_yaml ['leaky', 'yml'], yaml1 do |t1| + tmp_yaml ['curious', 'yml'], yaml2 do |t2| + File.open(t1.path) { |fh| fh.to_a } + assert_raises(NameError) do + File.open(t2.path) { |fh| fh.to_a } + end + end + end + end + private def tmp_yaml(name, contents) t = Tempfile.new name diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 136fda664c..5566563116 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -134,6 +134,15 @@ class QueryCacheTest < ActiveRecord::TestCase end end + def test_find_queries_with_multi_cache_blocks + Task.cache do + Task.cache do + assert_queries(2) { Task.find(1); Task.find(2) } + end + assert_queries(0) { Task.find(1); Task.find(1); Task.find(2) } + end + end + def test_count_queries_with_cache Task.cache do assert_queries(1) { Task.count; Task.count } diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb index 11dd32bfb8..71754cf0a2 100644 --- a/activerecord/test/cases/scoping/default_scoping_test.rb +++ b/activerecord/test/cases/scoping/default_scoping_test.rb @@ -178,7 +178,7 @@ class DefaultScopingTest < ActiveRecord::TestCase def test_unscope_select expected = Developer.order('salary ASC').collect { |dev| dev.name } - received = Developer.order('salary DESC').reverse_order.select(:name => "Jamis").unscope(:select).collect { |dev| dev.name } + received = Developer.order('salary DESC').reverse_order.select(:name).unscope(:select).collect { |dev| dev.name } assert_equal expected, received expected_2 = Developer.all.collect { |dev| dev.id } |