diff options
Diffstat (limited to 'activerecord')
26 files changed, 350 insertions, 64 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index a965fe0494..36d94fb38b 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,18 @@ ## Rails 4.0.0 (unreleased) ## +* Add `add_reference` and `remove_reference` schema statements. Aliases, `add_belongs_to` + and `remove_belongs_to` are acceptable. References are reversible. + Examples: + + # Create a user_id column + add_reference(:products, :user) + # Create a supplier_id, supplier_type columns and appropriate index + add_reference(:products, :supplier, polymorphic: true, index: true) + # Remove polymorphic reference + remove_reference(:products, :supplier, polymorphic: true) + + *Aleksey Magusev* + * Add `:default` and `:null` options to `column_exists?`. column_exists?(:testings, :taggable_id, :integer, null: false) @@ -7,14 +20,18 @@ *Aleksey Magusev* -* `ActiveRelation#inspect` no longer calls `#to_a`. This means that in places - where `#inspect` is implied (such as in the console), creating a relation - will not execute it anymore, you'll have to call `#to_a` when necessary: +* `ActiveRecord::Relation#inspect` now makes it clear that you are + dealing with a `Relation` object rather than an array:. + + User.where(:age => 30).inspect + # => <ActiveRecord::Relation [#<User ...>, #<User ...>, ...]> + + User.where(:age => 30).to_a.inspect + # => [#<User ...>, #<User ...>] - User.where(:age => 30) # => returns the relation - User.where(:age => 30).to_a # => executes the query and returns the loaded objects, as before + The number of records displayed will be limited to 10. - *Brian Cardarella* + *Brian Cardarella, Jon Leighton & Damien Mathieu* * Add `collation` and `ctype` support to PostgreSQL. These are available for PostgreSQL 8.4 or later. Example: @@ -852,7 +869,7 @@ * LRU cache in mysql and sqlite are now per-process caches. - * lib/active_record/connection_adapters/mysql_adapter.rb: LRU cache keys are per process id. + * lib/active_record/connection_adapters/mysql_adapter.rb: LRU cache keys are per process id. * lib/active_record/connection_adapters/sqlite_adapter.rb: ditto *Aaron Patterson* diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 4af4d28b74..49ab3ab808 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -6,7 +6,7 @@ module ActiveRecord included do # Returns a hash of all the attributes that have been specified for serialization as # keys and their class restriction as values. - class_attribute :serialized_attributes + class_attribute :serialized_attributes, instance_writer: false self.serialized_attributes = {} end 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 3b4537aab4..a6e16da730 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -56,7 +56,7 @@ module ActiveRecord end def select_all(arel, name = nil, binds = []) - if @query_cache_enabled + if @query_cache_enabled && !locked?(arel) sql = to_sql(arel, binds) cache_sql(sql, binds) { super(sql, name, binds) } else @@ -83,6 +83,14 @@ module ActiveRecord result.collect { |row| row.dup } end end + + def locked?(arel) + if arel.respond_to?(:locked) + arel.locked + else + false + end + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 6f9f0399db..60a9eee7c7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -31,7 +31,7 @@ module ActiveRecord # BigDecimals need to be put in a non-normalized form and quoted. when nil then "NULL" when BigDecimal then value.to_s('F') - when Numeric then value.to_s + when Numeric, ActiveSupport::Duration then value.to_s when Date, Time then "'#{quoted_date(value)}'" when Symbol then "'#{quote_string(value.to_s)}'" when Class then "'#{value.to_s}'" diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index df78ba6c5a..ef17dfbbc5 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -259,7 +259,7 @@ module ActiveRecord end # end EOV end - + # Adds index options to the indexes hash, keyed by column name # This is primarily used to track indexes that need to be created after the table # @@ -282,7 +282,7 @@ module ActiveRecord index_options = options.delete(:index) args.each do |col| column("#{col}_id", :integer, options) - column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil? + column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options end end @@ -441,17 +441,13 @@ module ActiveRecord # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided. # <tt>references</tt> and <tt>belongs_to</tt> are acceptable. # - # t.references(:goat) - # t.references(:goat, :polymorphic => true) - # t.belongs_to(:goat) + # t.references(:user) + # t.belongs_to(:supplier, polymorphic: true) + # def references(*args) options = args.extract_options! - polymorphic = options.delete(:polymorphic) - index_options = options.delete(:index) - args.each do |col| - @base.add_column(@table_name, "#{col}_id", :integer, options) - @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil? - @base.add_index(@table_name, polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options + args.each do |ref_name| + @base.add_reference(@table_name, ref_name, options) end end alias :belongs_to :references @@ -459,18 +455,16 @@ module ActiveRecord # Removes a reference. Optionally removes a +type+ column. # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable. # - # t.remove_references(:goat) - # t.remove_references(:goat, :polymorphic => true) - # t.remove_belongs_to(:goat) + # t.remove_references(:user) + # t.remove_belongs_to(:supplier, polymorphic: true) + # def remove_references(*args) options = args.extract_options! - polymorphic = options.delete(:polymorphic) - args.each do |col| - @base.remove_column(@table_name, "#{col}_id") - @base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil? + args.each do |ref_name| + @base.remove_reference(@table_name, ref_name, options) end end - alias :remove_belongs_to :remove_references + alias :remove_belongs_to :remove_references # Adds a column or columns of a specified type # 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 2b0ba2f479..65c7ef0153 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -441,6 +441,42 @@ module ActiveRecord indexes(table_name).detect { |i| i.name == index_name } end + # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided. + # <tt>add_reference</tt> and <tt>add_belongs_to</tt> are acceptable. + # + # ====== Create a user_id column + # add_reference(:products, :user) + # + # ====== Create a supplier_id and supplier_type columns + # add_belongs_to(:products, :supplier, polymorphic: true) + # + # ====== Create a supplier_id, supplier_type columns and appropriate index + # add_reference(:products, :supplier, polymorphic: true, index: true) + # + def add_reference(table_name, ref_name, options = {}) + polymorphic = options.delete(:polymorphic) + index_options = options.delete(:index) + add_column(table_name, "#{ref_name}_id", :integer, options) + add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic + add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options + end + alias :add_belongs_to :add_reference + + # Removes the reference(s). Also removes a +type+ column if one exists. + # <tt>remove_reference</tt>, <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable. + # + # ====== Remove the reference + # remove_reference(:products, :user, index: true) + # + # ====== Remove polymorphic reference + # remove_reference(:products, :supplier, polymorphic: true) + # + def remove_reference(table_name, ref_name, options = {}) + remove_column(table_name, "#{ref_name}_id") + remove_column(table_name, "#{ref_name}_type") if options[:polymorphic] + end + alias :remove_belongs_to :remove_reference + # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the # entire structure of the database. def structure_dump diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index 96b62fdd61..95f4360578 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -51,13 +51,15 @@ module ActiveRecord super || delegate.respond_to?(*args) end - [:create_table, :create_join_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method| + [:create_table, :create_join_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default, :add_reference, :remove_reference].each do |method| class_eval <<-EOV, __FILE__, __LINE__ + 1 def #{method}(*args) # def create_table(*args) record(:"#{method}", args) # record(:create_table, args) end # end EOV end + alias :add_belongs_to :add_reference + alias :remove_belongs_to :remove_reference private @@ -102,6 +104,16 @@ module ActiveRecord [:remove_timestamps, args] end + def invert_add_reference(args) + [:remove_reference, args] + end + alias :invert_add_belongs_to :invert_add_reference + + def invert_remove_reference(args) + [:add_reference, args] + end + alias :invert_remove_belongs_to :invert_remove_reference + # Forwards any missing method call to the \target. def method_missing(method, *args, &block) @delegate.send(method, *args, &block) diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb index 7b3d926d91..0015e3a567 100644 --- a/activerecord/lib/active_record/model.rb +++ b/activerecord/lib/active_record/model.rb @@ -103,7 +103,9 @@ module ActiveRecord def abstract_class? false end - + + # Defines the name of the table column which will store the class name on single-table + # inheritance situations. def inheritance_column 'type' end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 841681e542..7febb5539f 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -351,7 +351,7 @@ module ActiveRecord if respond_to?(method) send(method, attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) else - raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?" + raise ArgumentError, "Cannot build association `#{association_name}'. Are you trying to build a polymorphic one-to-one association?" end end end @@ -373,7 +373,7 @@ module ActiveRecord # }) # # Will update the name of the Person with ID 1, build a new associated - # person with the name `John', and mark the associated Person with ID 2 + # person with the name 'John', and mark the associated Person with ID 2 # for destruction. # # Also accepts an Array of attribute hashes: diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index e268d451e0..a39328b89b 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -514,6 +514,16 @@ module ActiveRecord @values.dup end + def inspect + limit = [limit_value, 11].compact.min + entries = loaded? ? to_a.take(limit) : limit(limit) + + entries.map!(&:inspect) + entries[10] = '...' if entries.size == 11 + + "#<#{self.class.name} [#{entries.join(', ')}]>" + end + private def references_eager_loaded_tables? diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index 2af5b02fb7..d836acf18f 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -43,7 +43,7 @@ module ActiveRecord extend ActiveSupport::Concern included do - class_attribute :stored_attributes + class_attribute :stored_attributes, instance_writer: false self.stored_attributes = {} end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index f1241502f5..fb3dfc2730 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -3,13 +3,17 @@ module ActiveRecord module DatabaseTasks # :nodoc: extend self - TASKS_PATTERNS = { - /mysql/ => ActiveRecord::Tasks::MySQLDatabaseTasks, - /postgresql/ => ActiveRecord::Tasks::PostgreSQLDatabaseTasks, - /sqlite/ => ActiveRecord::Tasks::SQLiteDatabaseTasks - } LOCAL_HOSTS = ['127.0.0.1', 'localhost'] + def register_task(pattern, task) + @tasks ||= {} + @tasks[pattern] = task + end + + register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks) + register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks) + register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks) + def create(*arguments) configuration = arguments.first class_for_adapter(configuration['adapter']).new(*arguments).create @@ -84,8 +88,8 @@ module ActiveRecord private def class_for_adapter(adapter) - key = TASKS_PATTERNS.keys.detect { |pattern| adapter[pattern] } - TASKS_PATTERNS[key] + key = @tasks.keys.detect { |pattern| adapter[pattern] } + @tasks[key] end def each_current_configuration(environment) diff --git a/activerecord/lib/rails/generators/active_record/model/templates/module.rb b/activerecord/lib/rails/generators/active_record/model/templates/module.rb index fca2908080..a3bf1c37b6 100644 --- a/activerecord/lib/rails/generators/active_record/model/templates/module.rb +++ b/activerecord/lib/rails/generators/active_record/model/templates/module.rb @@ -1,7 +1,7 @@ <% module_namespacing do -%> module <%= class_path.map(&:camelize).join('::') %> def self.table_name_prefix - '<%= class_path.join('_') %>_' + '<%= namespaced? ? namespaced_class_path.join('_') : class_path.join('_') %>_' end end <% end -%> diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb index 4111a5f808..a7b63d15c9 100644 --- a/activerecord/test/cases/column_test.rb +++ b/activerecord/test/cases/column_test.rb @@ -76,6 +76,12 @@ module ActiveRecord date_string = Time.now.utc.strftime("%F") assert_equal date_string, column.type_cast(date_string).strftime("%F") end + + def test_type_cast_duration_to_integer + column = Column.new("field", nil, "integer") + assert_equal 1800, column.type_cast(30.minutes) + assert_equal 7200, column.type_cast(2.hours) + end end end end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index afff020561..44d08a8ee4 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -5,7 +5,6 @@ require 'config' gem 'minitest' require 'minitest/autorun' require 'stringio' -require 'mocha' require 'cases/test_case' require 'active_record' diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index 063209389f..4614be9650 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -30,61 +30,57 @@ module ActiveRecord def test_references_column_type_adds_id with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, 'customer_id', :integer, {}] + @connection.expect :add_reference, nil, [:delete_me, :customer, {}] t.references :customer end end def test_remove_references_column_type_removes_id with_change_table do |t| - @connection.expect :remove_column, nil, [:delete_me, 'customer_id'] + @connection.expect :remove_reference, nil, [:delete_me, :customer, {}] t.remove_references :customer end end def test_add_belongs_to_works_like_add_references with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, 'customer_id', :integer, {}] + @connection.expect :add_reference, nil, [:delete_me, :customer, {}] t.belongs_to :customer end end def test_remove_belongs_to_works_like_remove_references with_change_table do |t| - @connection.expect :remove_column, nil, [:delete_me, 'customer_id'] + @connection.expect :remove_reference, nil, [:delete_me, :customer, {}] t.remove_belongs_to :customer end end def test_references_column_type_with_polymorphic_adds_type with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, 'taggable_id', :integer, {}] - @connection.expect :add_column, nil, [:delete_me, 'taggable_type', :string, {}] - t.references :taggable, :polymorphic => true + @connection.expect :add_reference, nil, [:delete_me, :taggable, polymorphic: true] + t.references :taggable, polymorphic: true end end def test_remove_references_column_type_with_polymorphic_removes_type with_change_table do |t| - @connection.expect :remove_column, nil, [:delete_me, 'taggable_id'] - @connection.expect :remove_column, nil, [:delete_me, 'taggable_type'] - t.remove_references :taggable, :polymorphic => true + @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true] + t.remove_references :taggable, polymorphic: true end end def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, 'taggable_id', :integer, {:null => false}] - @connection.expect :add_column, nil, [:delete_me, 'taggable_type', :string, {:null => false}] - t.references :taggable, :polymorphic => true, :null => false + @connection.expect :add_reference, nil, [:delete_me, :taggable, polymorphic: true, null: false] + t.references :taggable, polymorphic: true, null: false end end def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag with_change_table do |t| - @connection.expect :remove_column, nil, [:delete_me, 'taggable_id'] - @connection.expect :remove_column, nil, [:delete_me, 'taggable_type'] - t.remove_references :taggable, :polymorphic => true, :null => false + @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true, null: false] + t.remove_references :taggable, polymorphic: true, null: false end end diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index 7d026961be..f2213ee6aa 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -110,9 +110,9 @@ module ActiveRecord end def test_invert_add_index_with_name - @recorder.record :add_index, [:table, [:one, :two], {:name => "new_index"}] - remove = @recorder.inverse.first - assert_equal [:remove_index, [:table, {:name => "new_index"}]], remove + @recorder.record :add_index, [:table, [:one, :two], {:name => "new_index"}] + remove = @recorder.inverse.first + assert_equal [:remove_index, [:table, {:name => "new_index"}]], remove end def test_invert_add_index_with_no_options @@ -138,6 +138,30 @@ module ActiveRecord add = @recorder.inverse.first assert_equal [:add_timestamps, [:table]], add end + + def test_invert_add_reference + @recorder.record :add_reference, [:table, :taggable, { polymorphic: true }] + remove = @recorder.inverse.first + assert_equal [:remove_reference, [:table, :taggable, { polymorphic: true }]], remove + end + + def test_invert_add_belongs_to_alias + @recorder.record :add_belongs_to, [:table, :user] + remove = @recorder.inverse.first + assert_equal [:remove_reference, [:table, :user]], remove + end + + def test_invert_remove_reference + @recorder.record :remove_reference, [:table, :taggable, { polymorphic: true }] + add = @recorder.inverse.first + assert_equal [:add_reference, [:table, :taggable, { polymorphic: true }]], add + end + + def test_invert_remove_belongs_to_alias + @recorder.record :remove_belongs_to, [:table, :user] + add = @recorder.inverse.first + assert_equal [:add_reference, [:table, :user]], add + end end end end diff --git a/activerecord/test/cases/migration/helper.rb b/activerecord/test/cases/migration/helper.rb index 20f26786f0..768ebc5861 100644 --- a/activerecord/test/cases/migration/helper.rb +++ b/activerecord/test/cases/migration/helper.rb @@ -14,7 +14,7 @@ module ActiveRecord module TestHelper attr_reader :connection, :table_name - CONNECTION_METHODS = %w[add_column remove_column rename_column add_index change_column rename_table] + CONNECTION_METHODS = %w[add_column remove_column rename_column add_index change_column rename_table column_exists? index_exists? add_reference add_belongs_to remove_reference remove_references remove_belongs_to] class TestModel < ActiveRecord::Base self.table_name = :test_models diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb new file mode 100644 index 0000000000..144302bd4a --- /dev/null +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -0,0 +1,111 @@ +require "cases/migration/helper" + +module ActiveRecord + class Migration + class ReferencesStatementsTest < ActiveRecord::TestCase + include ActiveRecord::Migration::TestHelper + + self.use_transactional_fixtures = false + + def setup + super + @table_name = :test_models + + add_column table_name, :supplier_id, :integer + add_index table_name, :supplier_id + end + + def test_creates_reference_id_column + add_reference table_name, :user + assert column_exists?(table_name, :user_id, :integer) + end + + def test_does_not_create_reference_type_column + add_reference table_name, :taggable + refute column_exists?(table_name, :taggable_type, :string) + end + + def test_creates_reference_type_column + add_reference table_name, :taggable, polymorphic: true + assert column_exists?(table_name, :taggable_type, :string) + end + + def test_creates_reference_id_index + add_reference table_name, :user, index: true + assert index_exists?(table_name, :user_id) + end + + def test_does_not_create_reference_id_index + add_reference table_name, :user + refute index_exists?(table_name, :user_id) + end + + def test_creates_polymorphic_index + add_reference table_name, :taggable, polymorphic: true, index: true + assert index_exists?(table_name, [:taggable_id, :taggable_type]) + end + + def test_creates_reference_type_column_with_default + add_reference table_name, :taggable, polymorphic: { default: 'Photo' }, index: true + assert column_exists?(table_name, :taggable_type, :string, default: 'Photo') + end + + def test_creates_named_index + add_reference table_name, :tag, index: { name: 'index_taggings_on_tag_id' } + assert index_exists?(table_name, :tag_id, name: 'index_taggings_on_tag_id') + end + + def test_deletes_reference_id_column + remove_reference table_name, :supplier + refute column_exists?(table_name, :supplier_id, :integer) + end + + def test_deletes_reference_id_index + remove_reference table_name, :supplier + refute index_exists?(table_name, :supplier_id) + end + + def test_does_not_delete_reference_type_column + with_polymorphic_column do + remove_reference table_name, :supplier + + refute column_exists?(table_name, :supplier_id, :integer) + assert column_exists?(table_name, :supplier_type, :string) + end + end + + def test_deletes_reference_type_column + with_polymorphic_column do + remove_reference table_name, :supplier, polymorphic: true + refute column_exists?(table_name, :supplier_type, :string) + end + end + + def test_deletes_polymorphic_index + with_polymorphic_column do + remove_reference table_name, :supplier, polymorphic: true + refute index_exists?(table_name, [:supplier_id, :supplier_type]) + end + end + + def test_add_belongs_to_alias + add_belongs_to table_name, :user + assert column_exists?(table_name, :user_id, :integer) + end + + def test_remove_belongs_to_alias + remove_belongs_to table_name, :supplier + refute column_exists?(table_name, :supplier_id, :integer) + end + + private + + def with_polymorphic_column + add_column table_name, :supplier_type, :string + add_index table_name, [:supplier_id, :supplier_type] + + yield + end + end + end +end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 3daa033ed0..3a234f0cc1 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -196,7 +196,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase end def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to - assert_raise_with_message ArgumentError, "Cannot build association looter. Are you trying to build a polymorphic one-to-one association?" do + assert_raise_with_message ArgumentError, "Cannot build association `looter'. Are you trying to build a polymorphic one-to-one association?" do Treasure.new(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"}) end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 08f655d7fa..0153e74604 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -164,6 +164,14 @@ class QueryCacheTest < ActiveRecord::TestCase end end end + + def test_cache_is_ignored_for_locked_relations + task = Task.find 1 + + Task.cache do + assert_queries(2) { task.lock!; task.lock! } + end + end end class QueryCacheExpiryTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index 80ee74e41e..3dd11ae89d 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -216,6 +216,14 @@ module ActiveRecord def test_string_with_crazy_column assert_equal "'lo\\\\l'", @quoter.quote('lo\l', FakeColumn.new(:foo)) end + + def test_quote_duration + assert_equal "1800", @quoter.quote(30.minutes) + end + + def test_quote_duration_int_column + assert_equal "7200", @quoter.quote(2.hours, FakeColumn.new(:integer)) + end end end end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 8544d36aa8..8713b8d5e4 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1311,4 +1311,25 @@ class RelationTest < ActiveRecord::TestCase relation.merge! where: 'foo' end end + + test "relations show the records in #inspect" do + relation = Post.limit(2) + assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect + end + + test "relations limit the records in #inspect at 10" do + relation = Post.limit(11) + assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect + end + + test "already-loaded relations don't perform a new query in #inspect" do + relation = Post.limit(2) + relation.to_a + + expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>" + + assert_no_queries do + assert_equal expected, relation.inspect + end + end end diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb index a4c065e667..ce167509c1 100644 --- a/activerecord/test/cases/serialization_test.rb +++ b/activerecord/test/cases/serialization_test.rb @@ -51,4 +51,11 @@ class SerializationTest < ActiveRecord::TestCase assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}" end end + + def test_serialized_attributes_are_class_level_settings + assert_raise NoMethodError do + topic = Topic.new + topic.serialized_attributes = [] + end + end end diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index 7f2b8945f9..3e60b62fd5 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -120,4 +120,11 @@ class StoreTest < ActiveRecord::TestCase test "stored attributes are returned" do assert_equal [:color, :homepage], Admin::User.stored_attributes[:settings] end + + test "stores_attributes are class level settings" do + assert_raise NoMethodError do + @john.stored_attributes = {} + end + end + end diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index 8c96a8aaa1..4f3489b7a5 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -16,6 +16,22 @@ module ActiveRecord :postgresql => :postgresql_tasks, :sqlite3 => :sqlite_tasks } + + class DatabaseTasksRegisterTask < ActiveRecord::TestCase + def test_register_task + klazz = Class.new do + def initialize(*arguments); end + def structure_dump(filename); end + end + instance = klazz.new + + klazz.stubs(:new).returns instance + instance.expects(:structure_dump).with("awesome-file.sql") + + ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz) + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :foo}, "awesome-file.sql") + end + end class DatabaseTasksCreateTest < ActiveRecord::TestCase include DatabaseTasksSetupper |