aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md92
-rw-r--r--activerecord/lib/active_record.rb1
-rw-r--r--activerecord/lib/active_record/associations/alias_tracker.rb2
-rw-r--r--activerecord/lib/active_record/associations/association.rb2
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb4
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb15
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb8
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb48
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb13
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb16
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb20
-rw-r--r--activerecord/lib/active_record/base.rb46
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb10
-rw-r--r--activerecord/lib/active_record/connection_handling.rb1
-rw-r--r--activerecord/lib/active_record/core.rb141
-rw-r--r--activerecord/lib/active_record/explain.rb8
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb41
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb8
-rw-r--r--activerecord/lib/active_record/migration.rb9
-rw-r--r--activerecord/lib/active_record/model.rb167
-rw-r--r--activerecord/lib/active_record/model_schema.rb47
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb8
-rw-r--r--activerecord/lib/active_record/persistence.rb4
-rw-r--r--activerecord/lib/active_record/query_cache.rb12
-rw-r--r--activerecord/lib/active_record/railtie.rb11
-rw-r--r--activerecord/lib/active_record/readonly_attributes.rb3
-rw-r--r--activerecord/lib/active_record/relation/batches.rb4
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb6
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb5
-rw-r--r--activerecord/lib/active_record/result.rb2
-rw-r--r--activerecord/lib/active_record/serialization.rb10
-rw-r--r--activerecord/lib/active_record/timestamp.rb5
-rw-r--r--activerecord/lib/active_record/transactions.rb5
-rw-r--r--activerecord/test/cases/adapter_test.rb6
-rw-r--r--activerecord/test/cases/adapters/mysql/connection_test.rb22
-rw-r--r--activerecord/test/cases/adapters/mysql/sql_types_test.rb14
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb12
-rw-r--r--activerecord/test/cases/adapters/mysql2/sql_types_test.rb14
-rw-r--r--activerecord/test/cases/adapters/sqlite3/copy_table_test.rb9
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb6
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb13
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb2
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb6
-rw-r--r--activerecord/test/cases/base_test.rb14
-rw-r--r--activerecord/test/cases/batches_test.rb8
-rw-r--r--activerecord/test/cases/column_test.rb8
-rw-r--r--activerecord/test/cases/connection_adapters/connection_handler_test.rb4
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb14
-rw-r--r--activerecord/test/cases/defaults_test.rb8
-rw-r--r--activerecord/test/cases/inclusion_test.rb133
-rw-r--r--activerecord/test/cases/inheritance_test.rb11
-rw-r--r--activerecord/test/cases/migration/change_schema_test.rb20
-rw-r--r--activerecord/test/cases/multiple_db_test.rb4
-rw-r--r--activerecord/test/cases/persistence_test.rb13
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb18
-rw-r--r--activerecord/test/cases/primary_keys_test.rb4
-rw-r--r--activerecord/test/cases/query_cache_test.rb11
-rw-r--r--activerecord/test/cases/relation_test.rb6
-rw-r--r--activerecord/test/cases/relations_test.rb9
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb6
-rw-r--r--activerecord/test/cases/serialization_test.rb16
-rw-r--r--activerecord/test/cases/serialized_attribute_test.rb16
-rw-r--r--activerecord/test/cases/transactions_test.rb15
-rw-r--r--activerecord/test/cases/unconnected_test.rb6
-rw-r--r--activerecord/test/cases/validations/i18n_generate_message_validation_test.rb14
-rw-r--r--activerecord/test/models/teapot.rb35
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb22
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb22
-rw-r--r--activerecord/test/schema/schema.rb6
-rw-r--r--activerecord/test/support/connection.rb6
79 files changed, 638 insertions, 751 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index ffd19a5334..1d43840573 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,63 @@
## Rails 4.0.0 (unreleased) ##
+* Fix `find_in_batches` crashing when IDs are strings and start option is not specified.
+
+ *Alexis Bernard*
+
+* `AR::Base#attributes_before_type_cast` now returns unserialized values for serialized attributes.
+
+ *Nikita Afanasenko*
+
+* Use query cache/uncache when using DATABASE_URL.
+ Fix #6951.
+
+ *kennyj*
+
+* Added `#none!` method for mutating `ActiveRecord::Relation` objects to a NullRelation.
+ It acts like `#none` but modifies relation in place.
+
+ *Juanjo Bazán*
+
+* Fix bug where `update_columns` and `update_column` would not let you update the primary key column.
+
+ *Henrik Nyh*
+
+* The `create_table` method raises an `ArgumentError` when the primary key column is redefined.
+ Fix #6378
+
+ *Yves Senn*
+
+* `ActiveRecord::AttributeMethods#[]` raises `ActiveModel::MissingAttributeError`
+ error if the given attribute is missing. Fixes #5433.
+
+ class Person < ActiveRecord::Base
+ belongs_to :company
+ end
+
+ # Before:
+ person = Person.select('id').first
+ person[:name] # => nil
+ person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person[:company_id] # => nil
+ person.company # => nil
+
+ # After:
+ person = Person.select('id').first
+ person[:name] # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person[:company_id] # => ActiveModel::MissingAttributeError: missing_attribute: company_id
+ person.company # => ActiveModel::MissingAttributeError: missing_attribute: company_id
+
+ *Francesco Rodriguez*
+
+* Small binary fields use the `VARBINARY` MySQL type, instead of `TINYBLOB`.
+
+ *Victor Costan*
+
+* Decode URI encoded attributes on database connection URLs.
+
+ *Shawn Veader*
+
* Add `find_or_create_by`, `find_or_create_by!` and
`find_or_initialize_by` methods to `Relation`.
@@ -38,12 +96,12 @@
*Jon Leighton*
-* Fix bug with presence validation of associations. Would incorrectly add duplicated errors
+* Fix bug with presence validation of associations. Would incorrectly add duplicated errors
when the association was blank. Bug introduced in 1fab518c6a75dac5773654646eb724a59741bc13.
*Scott Willson*
-* Fix bug where sum(expression) returns string '0' for no matching records
+* Fix bug where sum(expression) returns string '0' for no matching records.
Fixes #7439
*Tim Macfarlane*
@@ -338,7 +396,7 @@
* Fix AR#dup to nullify the validation errors in the dup'ed object. Previously the original
and the dup'ed object shared the same errors.
- * Christian Seiler*
+ *Christian Seiler*
* Raise `ArgumentError` if list of attributes to change is empty in `update_all`.
@@ -926,34 +984,6 @@
*Aaron Patterson*
-* Added the `ActiveRecord::Model` module which can be included in a
- class as an alternative to inheriting from `ActiveRecord::Base`:
-
- class Post
- include ActiveRecord::Model
- end
-
- Please note:
-
- * Up until now it has been safe to assume that all AR models are
- descendants of `ActiveRecord::Base`. This is no longer a safe
- assumption, but it may transpire that there are areas of the
- code which still make this assumption. So there may be
- 'teething difficulties' with this feature. (But please do try it
- and report bugs.)
-
- * Plugins & libraries etc that add methods to `ActiveRecord::Base`
- will not be compatible with `ActiveRecord::Model`. Those libraries
- should add to `ActiveRecord::Model` instead (which is included in
- `Base`), or better still, avoid monkey-patching AR and instead
- provide a module that users can include where they need it.
-
- * To minimise the risk of conflicts with other code, it is
- advisable to include `ActiveRecord::Model` early in your class
- definition.
-
- *Jon Leighton*
-
* PostgreSQL hstore records can be created.
*Aaron Patterson*
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 1675127ab0..45122539f1 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -43,7 +43,6 @@ module ActiveRecord
autoload :Integration
autoload :Migration
autoload :Migrator, 'active_record/migration'
- autoload :Model
autoload :ModelSchema
autoload :NestedAttributes
autoload :Observer
diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb
index 84540a7000..0c23029981 100644
--- a/activerecord/lib/active_record/associations/alias_tracker.rb
+++ b/activerecord/lib/active_record/associations/alias_tracker.rb
@@ -8,7 +8,7 @@ module ActiveRecord
attr_reader :aliases, :table_joins, :connection
# table_joins is an array of arel joins which might conflict with the aliases we assign here
- def initialize(connection = ActiveRecord::Model.connection, table_joins = [])
+ def initialize(connection = Base.connection, table_joins = [])
@aliases = Hash.new { |h,k| h[k] = initial_count_for(k) }
@table_joins = table_joins
@connection = connection
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 2a5f727728..99e7383d42 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -85,7 +85,7 @@ module ActiveRecord
end
def scoped
- ActiveSupport::Deprecation.warn("#scoped is deprecated. use #scope instead.")
+ ActiveSupport::Deprecation.warn "#scoped is deprecated. use #scope instead."
scope
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 7f39d3083e..54215cf88d 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -576,7 +576,9 @@ module ActiveRecord
args.shift if args.first.is_a?(Hash) && args.first.empty?
collection = fetch_first_or_last_using_find?(args) ? scope : load_target
- collection.send(type, *args).tap {|it| set_inverse_instance it }
+ collection.send(type, *args).tap do |record|
+ set_inverse_instance record if record.is_a? ActiveRecord::Base
+ end
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 1dd9a3d45d..437fd00948 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -59,7 +59,7 @@ module ActiveRecord
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord"
end
- if [Base, Model].include?(active_record_super)
+ if superclass == Base
super
else
# If B < A and A defines its own attribute method, then we don't want to overwrite that.
@@ -269,17 +269,24 @@ module ActiveRecord
end
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
- # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
- # (Alias for <tt>read_attribute</tt>).
+ # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). It raises
+ # <tt>ActiveModel::MissingAttributeError</tt> if the identified attribute is missing.
+ #
+ # Alias for the <tt>read_attribute</tt> method.
#
# class Person < ActiveRecord::Base
+ # belongs_to :organization
# end
#
# person = Person.new(name: 'Francesco', age: '22')
# person[:name] # => "Francesco"
# person[:age] # => 22
+ #
+ # person = Person.select('id').first
+ # person[:name] # => ActiveModel::MissingAttributeError: missing attribute: name
+ # person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
def [](attr_name)
- read_attribute(attr_name)
+ read_attribute(attr_name) { |n| missing_attribute(n, caller) }
end
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 59f209cec8..0333605eac 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -2,11 +2,6 @@ require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/deprecation'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :partial_writes, instance_accessor: false
- self.partial_writes = true
- end
-
module AttributeMethods
module Dirty # :nodoc:
extend ActiveSupport::Concern
@@ -18,7 +13,8 @@ module ActiveRecord
raise "You cannot include Dirty after Timestamp"
end
- config_attribute :partial_writes
+ class_attribute :partial_writes, instance_writer: false
+ self.partial_writes = true
def self.partial_updates=(v); self.partial_writes = v; end
def self.partial_updates?; partial_writes?; end
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 46fd6ebfb3..90701938e5 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -1,8 +1,4 @@
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :attribute_types_cached_by_default, instance_accessor: false
- end
-
module AttributeMethods
module Read
extend ActiveSupport::Concern
@@ -10,7 +6,8 @@ module ActiveRecord
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
included do
- config_attribute :attribute_types_cached_by_default
+ class_attribute :attribute_types_cached_by_default, instance_writer: false
+ self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
end
module ClassMethods
@@ -35,36 +32,21 @@ module ActiveRecord
protected
- # We want to generate the methods via module_eval rather than
- # define_method, because define_method is slower on dispatch and
- # uses more memory (because it creates a closure).
+ # We want to generate the methods via module_eval rather than define_method,
+ # because define_method is slower on dispatch and uses more memory (because it
+ # creates a closure).
#
- # But sometimes the database might return columns with
- # characters that are not allowed in normal method names (like
- # 'my_column(omg)'. So to work around this we first define with
- # the __temp__ identifier, and then use alias method to rename
- # it to what we want.
- #
- # We are also defining a constant to hold the frozen string of
- # the attribute name. Using a constant means that we do not have
- # to allocate an object on each call to the attribute method.
- # Making it frozen means that it doesn't get duped when used to
- # key the @attributes_cache in read_attribute.
- def define_method_attribute(name)
- safe_name = name.unpack('h*').first
+ # But sometimes the database might return columns with characters that are not
+ # allowed in normal method names (like 'my_column(omg)'. So to work around this
+ # we first define with the __temp__ identifier, and then use alias method to
+ # rename it to what we want.
+ def define_method_attribute(attr_name)
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
- module AttrNames
- unless defined? ATTR_#{safe_name}
- ATTR_#{safe_name} = #{name.inspect}.freeze
- end
+ def __temp__
+ read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
end
-
- def __temp__#{safe_name}
- read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) }
- end
-
- alias_method #{name.inspect}, :__temp__#{safe_name}
- undef_method :__temp__#{safe_name}
+ alias_method '#{attr_name}', :__temp__
+ undef_method :__temp__
STR
end
@@ -79,8 +61,6 @@ module ActiveRecord
end
end
- ActiveRecord::Model.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
-
# Returns the value of the attribute identified by <tt>attr_name</tt> after
# it has been typecast (for example, "2004-12-12" in a data column is cast
# to a date object, like Date.new(2004, 12, 12)).
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 9994a81ede..5b9ed81424 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -45,7 +45,8 @@ module ActiveRecord
end
def serialized_attributes
- ActiveSupport::Deprecation.warn("Instance level serialized_attributes method is deprecated, please use class level method.")
+ message = "Instance level serialized_attributes method is deprecated, please use class level method."
+ ActiveSupport::Deprecation.warn message
defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes
end
@@ -118,6 +119,16 @@ module ActiveRecord
super
end
end
+
+ def attributes_before_type_cast
+ super.dup.tap do |attributes|
+ self.class.serialized_attributes.each_key do |key|
+ if attributes.key?(key)
+ attributes[key] = attributes[key].unserialized_value
+ end
+ end
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index f36a5806a9..806dc5b1d2 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -1,13 +1,4 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :time_zone_aware_attributes, instance_accessor: false
- self.time_zone_aware_attributes = false
-
- mattr_accessor :skip_time_zone_conversion_for_attributes, instance_accessor: false
- self.skip_time_zone_conversion_for_attributes = []
- end
-
module AttributeMethods
module TimeZoneConversion
class Type # :nodoc:
@@ -28,8 +19,11 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :time_zone_aware_attributes, global: true
- config_attribute :skip_time_zone_conversion_for_attributes
+ mattr_accessor :time_zone_aware_attributes, instance_writer: false
+ self.time_zone_aware_attributes = false
+
+ class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
+ self.skip_time_zone_conversion_for_attributes = []
end
module ClassMethods
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index cd33494cc3..fa9097db1f 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -9,19 +9,15 @@ module ActiveRecord
module ClassMethods
protected
-
- # See define_method_attribute in read.rb for an explanation of
- # this code.
- def define_method_attribute=(name)
- safe_name = name.unpack('h*').first
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
- def __temp__#{safe_name}=(value)
- write_attribute(AttrNames::ATTR_#{safe_name}, value)
+ def define_method_attribute=(attr_name)
+ if attr_name =~ ActiveModel::AttributeMethods::NAME_COMPILABLE_REGEXP
+ generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__)
+ else
+ generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value|
+ write_attribute(attr_name, new_value)
+ end
end
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
- undef_method :__temp__#{safe_name}=
- STR
- end
+ end
end
# Updates the attribute identified by <tt>attr_name</tt> with the
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index a4705b24ca..eabbd80f66 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -321,8 +321,48 @@ module ActiveRecord #:nodoc:
# So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
# instances in the current object space.
class Base
- include ActiveRecord::Model
+ extend ActiveModel::Observing::ClassMethods
+ extend ActiveModel::Naming
+
+ extend ActiveSupport::Benchmarkable
+ extend ActiveSupport::DescendantsTracker
+
+ extend ConnectionHandling
+ extend QueryCache::ClassMethods
+ extend Querying
+ extend Translation
+ extend DynamicMatchers
+ extend Explain
+ extend ConnectionHandling
+
+ include Persistence
+ include ReadonlyAttributes
+ include ModelSchema
+ include Inheritance
+ include Scoping
+ include Sanitization
+ include AttributeAssignment
+ include ActiveModel::Conversion
+ include Integration
+ include Validations
+ include CounterCache
+ include Locking::Optimistic
+ include Locking::Pessimistic
+ include AttributeMethods
+ include Callbacks
+ include ActiveModel::Observing
+ include Timestamp
+ include Associations
+ include ActiveModel::SecurePassword
+ include AutosaveAssociation
+ include NestedAttributes
+ include Aggregations
+ include Transactions
+ include Reflection
+ include Serialization
+ include Store
+ include Core
end
-end
-ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Model::DeprecationProxy.new)
+ ActiveSupport.run_load_hooks(:active_record, Base)
+end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 42bd16db80..1da95f451f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -441,11 +441,11 @@ module ActiveRecord
end
def new_connection
- ActiveRecord::Model.send(spec.adapter_method, spec.config)
+ Base.send(spec.adapter_method, spec.config)
end
def current_connection_id #:nodoc:
- ActiveRecord::Model.connection_id ||= Thread.current.object_id
+ Base.connection_id ||= Thread.current.object_id
end
def checkout_new_connection
@@ -567,10 +567,10 @@ module ActiveRecord
class_to_pool[klass] ||= begin
until pool = pool_for(klass)
klass = klass.superclass
- break unless klass < ActiveRecord::Tag
+ break unless klass <= Base
end
- class_to_pool[klass] = pool || pool_for(ActiveRecord::Model)
+ class_to_pool[klass] = pool
end
end
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 d61731633a..38960ab873 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -234,6 +234,10 @@ module ActiveRecord
name = name.to_s
type = type.to_sym
+ if primary_key_column_name == name
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
+ end
+
column = self[name] || new_column_definition(@base, name, type)
limit = options.fetch(:limit) do
@@ -302,6 +306,11 @@ module ActiveRecord
definition
end
+ def primary_key_column_name
+ primary_key_column = columns.detect { |c| c.type == :primary_key }
+ primary_key_column && primary_key_column.name
+ end
+
def native
@base.native_database_types
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 0cb219767b..8517ce5fc5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -3,7 +3,7 @@ require 'bigdecimal'
require 'bigdecimal/util'
require 'active_support/core_ext/benchmark'
require 'active_record/connection_adapters/schema_cache'
-require 'active_record/connection_adapters/abstract/schema_dumper'
+require 'active_record/connection_adapters/abstract/schema_dumper'
require 'monitor'
require 'active_support/deprecation'
@@ -263,7 +263,8 @@ module ActiveRecord
end
def transaction_joinable=(joinable)
- ActiveSupport::Deprecation.warn "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
+ message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
+ ActiveSupport::Deprecation.warn message
@transaction.joinable = joinable
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 7da77af3a9..84e73e6f0f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -498,6 +498,13 @@ module ActiveRecord
# Maps logical Rails types to MySQL-specific data types.
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
case type.to_s
+ when 'binary'
+ case limit
+ when 0..0xfff; "varbinary(#{limit})"
+ when nil; "blob"
+ when 0x1000..0xffffffff; "blob(#{limit})"
+ else raise(ActiveRecordError, "No binary type has character length #{limit}")
+ end
when 'integer'
case limit
when 1; 'tinyint'
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 816b5e17c1..80984f39c9 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -94,7 +94,7 @@ module ActiveRecord
case type
when :string, :text then value
- when :integer then value.to_i
+ when :integer then klass.value_to_integer(value)
when :float then value.to_f
when :decimal then klass.value_to_decimal(value)
when :datetime, :timestamp then klass.string_to_time(value)
@@ -107,14 +107,15 @@ module ActiveRecord
end
def type_cast_code(var_name)
- ActiveSupport::Deprecation.warn("Column#type_cast_code is deprecated in favor of" \
- "using Column#type_cast only, and it is going to be removed in future Rails versions.")
+ message = "Column#type_cast_code is deprecated in favor of using Column#type_cast only, " \
+ "and it is going to be removed in future Rails versions."
+ ActiveSupport::Deprecation.warn message
klass = self.class.name
case type
when :string, :text then var_name
- when :integer then "(#{var_name}.to_i)"
+ when :integer then "#{klass}.value_to_integer(#{var_name})"
when :float then "#{var_name}.to_f"
when :decimal then "#{klass}.value_to_decimal(#{var_name})"
when :datetime, :timestamp then "#{klass}.string_to_time(#{var_name})"
@@ -197,6 +198,17 @@ module ActiveRecord
end
end
+ # Used to convert values to integer.
+ # handle the case when an integer column is used to store boolean values
+ def value_to_integer(value)
+ case value
+ when TrueClass, FalseClass
+ value ? 1 : 0
+ else
+ value.to_i
+ end
+ end
+
# convert something to a BigDecimal
def value_to_decimal(value)
# Using .class is faster than .is_a? and
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index b9a61f7d91..09250d3c01 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -73,6 +73,8 @@ module ActiveRecord
:database => config.path.sub(%r{^/},""),
:host => config.host }
spec.reject!{ |_,value| value.blank? }
+ uri_parser = URI::Parser.new
+ spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) }
if config.query
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
spec.merge!(options)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
index 553985bd1e..34d7a246b2 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
@@ -221,10 +221,9 @@ module ActiveRecord
end
def outside_transaction?
- ActiveSupport::Deprecation.warn(
- "#outside_transaction? is deprecated. This method was only really used " \
- "internally, but you can use #transaction_open? instead."
- )
+ message = "#outside_transaction? is deprecated. This method was only really used " \
+ "internally, but you can use #transaction_open? instead."
+ ActiveSupport::Deprecation.warn message
@connection.transaction_status == PGconn::PQTRANS_IDLE
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 4d5cb72c67..b89e9a01a8 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -251,7 +251,7 @@ module ActiveRecord
value = super
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
- value.encode! 'utf-8'
+ value = value.encode Encoding::UTF_8
end
value
end
@@ -519,24 +519,22 @@ module ActiveRecord
def copy_table(from, to, options = {}) #:nodoc:
from_primary_key = primary_key(from)
- options[:primary_key] = from_primary_key if from_primary_key != 'id'
- unless options[:primary_key]
- options[:id] = columns(from).detect{|c| c.name == 'id'}.present? && from_primary_key == 'id'
- end
+ options[:id] = false
create_table(to, options) do |definition|
@definition = definition
+ @definition.primary_key(from_primary_key) if from_primary_key.present?
columns(from).each do |column|
column_name = options[:rename] ?
(options[:rename][column.name] ||
options[:rename][column.name.to_sym] ||
column.name) : column.name
+ next if column_name == from_primary_key
@definition.column(column_name, column.type,
:limit => column.limit, :default => column.default,
:precision => column.precision, :scale => column.scale,
:null => column.null)
end
- @definition.primary_key(from_primary_key) if from_primary_key
yield @definition if block_given?
end
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index 3531be05bf..8ce7a7a463 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -1,4 +1,3 @@
-
module ActiveRecord
module ConnectionHandling
# Establishes the connection to the database. Accepts a hash as input where
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index f97c363871..98032db2ef 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -4,73 +4,6 @@ require 'thread'
module ActiveRecord
ActiveSupport.on_load(:active_record_config) do
- ##
- # :singleton-method:
- #
- # Accepts a logger conforming to the interface of Log4r which is then
- # passed on to any new database connections made and which can be
- # retrieved on both a class and instance level by calling +logger+.
- mattr_accessor :logger, instance_accessor: false
-
- ##
- # :singleton-method:
- # Contains the database configuration - as is typically stored in config/database.yml -
- # as a Hash.
- #
- # For example, the following database.yml...
- #
- # development:
- # adapter: sqlite3
- # database: db/development.sqlite3
- #
- # production:
- # adapter: sqlite3
- # database: db/production.sqlite3
- #
- # ...would result in ActiveRecord::Base.configurations to look like this:
- #
- # {
- # 'development' => {
- # 'adapter' => 'sqlite3',
- # 'database' => 'db/development.sqlite3'
- # },
- # 'production' => {
- # 'adapter' => 'sqlite3',
- # 'database' => 'db/production.sqlite3'
- # }
- # }
- mattr_accessor :configurations, instance_accessor: false
- self.configurations = {}
-
- ##
- # :singleton-method:
- # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
- # dates and times from the database. This is set to :utc by default.
- mattr_accessor :default_timezone, instance_accessor: false
- self.default_timezone = :utc
-
- ##
- # :singleton-method:
- # Specifies the format to use when dumping the database schema with Rails'
- # Rakefile. If :sql, the schema is dumped as (potentially database-
- # specific) SQL statements. If :ruby, the schema is dumped as an
- # ActiveRecord::Schema file which can be loaded into any database that
- # supports migrations. Use :ruby if you want to have different database
- # adapters for, e.g., your development and test environments.
- mattr_accessor :schema_format, instance_accessor: false
- self.schema_format = :ruby
-
- ##
- # :singleton-method:
- # Specify whether or not to use timestamps for migration versions
- mattr_accessor :timestamped_migrations, instance_accessor: false
- self.timestamped_migrations = true
-
- mattr_accessor :connection_handler, instance_accessor: false
- self.connection_handler = ConnectionAdapters::ConnectionHandler.new
-
- mattr_accessor :dependent_restrict_raises, instance_accessor: false
- self.dependent_restrict_raises = true
end
module Core
@@ -79,12 +12,68 @@ module ActiveRecord
included do
##
# :singleton-method:
- # The connection handler
- config_attribute :connection_handler
+ #
+ # Accepts a logger conforming to the interface of Log4r which is then
+ # passed on to any new database connections made and which can be
+ # retrieved on both a class and instance level by calling +logger+.
+ mattr_accessor :logger, instance_writer: false
+
+ ##
+ # :singleton-method:
+ # Contains the database configuration - as is typically stored in config/database.yml -
+ # as a Hash.
+ #
+ # For example, the following database.yml...
+ #
+ # development:
+ # adapter: sqlite3
+ # database: db/development.sqlite3
+ #
+ # production:
+ # adapter: sqlite3
+ # database: db/production.sqlite3
+ #
+ # ...would result in ActiveRecord::Base.configurations to look like this:
+ #
+ # {
+ # 'development' => {
+ # 'adapter' => 'sqlite3',
+ # 'database' => 'db/development.sqlite3'
+ # },
+ # 'production' => {
+ # 'adapter' => 'sqlite3',
+ # 'database' => 'db/production.sqlite3'
+ # }
+ # }
+ mattr_accessor :configurations, instance_writer: false
+ self.configurations = {}
- %w(logger configurations default_timezone schema_format timestamped_migrations).each do |name|
- config_attribute name, global: true
- end
+ ##
+ # :singleton-method:
+ # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
+ # dates and times from the database. This is set to :utc by default.
+ mattr_accessor :default_timezone, instance_writer: false
+ self.default_timezone = :utc
+
+ ##
+ # :singleton-method:
+ # Specifies the format to use when dumping the database schema with Rails'
+ # Rakefile. If :sql, the schema is dumped as (potentially database-
+ # specific) SQL statements. If :ruby, the schema is dumped as an
+ # ActiveRecord::Schema file which can be loaded into any database that
+ # supports migrations. Use :ruby if you want to have different database
+ # adapters for, e.g., your development and test environments.
+ mattr_accessor :schema_format, instance_writer: false
+ self.schema_format = :ruby
+
+ ##
+ # :singleton-method:
+ # Specify whether or not to use timestamps for migration versions
+ mattr_accessor :timestamped_migrations, instance_writer: false
+ self.timestamped_migrations = true
+
+ class_attribute :connection_handler, instance_writer: false
+ self.connection_handler = ConnectionAdapters::ConnectionHandler.new
end
module ClassMethods
@@ -139,7 +128,13 @@ module ActiveRecord
# Returns the Arel engine.
def arel_engine
- @arel_engine ||= connection_handler.retrieve_connection_pool(self) ? self : active_record_super.arel_engine
+ @arel_engine ||= begin
+ if Base == self || connection_handler.retrieve_connection_pool(self)
+ self
+ else
+ superclass.arel_engine
+ end
+ end
end
private
diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb
index 9e0390bed1..af772996f1 100644
--- a/activerecord/lib/active_record/explain.rb
+++ b/activerecord/lib/active_record/explain.rb
@@ -1,12 +1,10 @@
require 'active_support/lazy_load_hooks'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false
- end
-
module Explain
- delegate :auto_explain_threshold_in_seconds, :auto_explain_threshold_in_seconds=, to: 'ActiveRecord::Model'
+ def self.extended(base)
+ base.mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false
+ end
# If auto explain is enabled, this method triggers EXPLAIN logging for the
# queries triggered by the block if it takes more than the threshold as a
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 7f1d62af39..29a99a5336 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -553,7 +553,7 @@ module ActiveRecord
rows[table_name] = fixtures.map do |label, fixture|
row = fixture.to_hash
- if model_class && model_class < ActiveRecord::Model
+ if model_class && model_class < ActiveRecord::Base
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
if model_class.record_timestamps
timestamp_column_names.each do |c_name|
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 35273b0d81..a448fa1f5c 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -1,29 +1,22 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- # Determine whether to store the full constant name including namespace when using STI
- mattr_accessor :store_full_sti_class, instance_accessor: false
- self.store_full_sti_class = true
- end
-
module Inheritance
extend ActiveSupport::Concern
included do
- config_attribute :store_full_sti_class
+ # Determine whether to store the full constant name including namespace when using STI
+ class_attribute :store_full_sti_class, instance_writer: false
+ self.store_full_sti_class = true
end
module ClassMethods
# True if this isn't a concrete subclass needing a STI type condition.
def descends_from_active_record?
- sup = active_record_super
-
- if sup.abstract_class?
- sup.descends_from_active_record?
- elsif self == Base
+ if self == Base
false
+ elsif superclass.abstract_class?
+ superclass.descends_from_active_record?
else
- [Base, Model].include?(sup) || !columns_hash.include?(inheritance_column)
+ superclass == Base || !columns_hash.include?(inheritance_column)
end
end
@@ -40,9 +33,8 @@ module ActiveRecord
@symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
end
- # Returns the class descending directly from ActiveRecord::Base (or
- # that includes ActiveRecord::Model), or an abstract class, if any, in
- # the inheritance hierarchy.
+ # Returns the class descending directly from ActiveRecord::Base, or
+ # an abstract class, if any, in the inheritance hierarchy.
#
# If A extends AR::Base, A.base_class will return A. If B descends from A
# through some arbitrarily deep hierarchy, B.base_class will return A.
@@ -50,15 +42,14 @@ module ActiveRecord
# If B < A and C < B and if A is an abstract_class then both B.base_class
# and C.base_class would return B as the answer since A is an abstract_class.
def base_class
- unless self < ActiveRecord::Tag
+ unless self < Base
raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
end
- sup = active_record_super
- if sup == Base || sup == Model || sup.abstract_class?
+ if superclass == Base || superclass.abstract_class?
self
else
- sup.base_class
+ superclass.base_class
end
end
@@ -97,14 +88,6 @@ module ActiveRecord
sti_class.allocate.init_with('attributes' => record, 'column_types' => column_types)
end
- # For internal use.
- #
- # If this class includes ActiveRecord::Model then it won't have a
- # superclass. So this provides a way to get to the 'root' (ActiveRecord::Model).
- def active_record_super #:nodoc:
- superclass < Model ? superclass : Model
- end
-
protected
# Returns the class type of the record using the current module as a prefix. So descendants of
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index e96ed00f9c..035c77c424 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -1,9 +1,4 @@
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :lock_optimistically, instance_accessor: false
- self.lock_optimistically = true
- end
-
module Locking
# == What is Optimistic Locking
#
@@ -56,7 +51,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :lock_optimistically
+ class_attribute :lock_optimistically, instance_writer: false
+ self.lock_optimistically = true
end
def locking_enabled? #:nodoc:
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index d5ee98382d..5499f37802 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -342,7 +342,9 @@ module ActiveRecord
end
def call(env)
- ActiveRecord::Migration.check_pending!
+ ActiveRecord::Base.logger.quietly do
+ ActiveRecord::Migration.check_pending!
+ end
@app.call(env)
end
end
@@ -730,9 +732,8 @@ module ActiveRecord
running = runnable
if block_given?
- ActiveSupport::Deprecation.warn(<<-eomsg)
-block argument to migrate is deprecated, please filter migrations before constructing the migrator
- eomsg
+ message = "block argument to migrate is deprecated, please filter migrations before constructing the migrator"
+ ActiveSupport::Deprecation.warn message
running.select! { |m| yield m }
end
diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb
deleted file mode 100644
index f059840f4d..0000000000
--- a/activerecord/lib/active_record/model.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-require 'active_support/core_ext/module/attribute_accessors'
-
-module ActiveRecord
- module Configuration # :nodoc:
- # This just abstracts out how we define configuration options in AR. Essentially we
- # have mattr_accessors on the ActiveRecord:Model constant that define global defaults.
- # Classes that then use AR get class_attributes defined, which means that when they
- # are assigned the default will be overridden for that class and subclasses. (Except
- # when options[:global] == true, in which case there is one global value always.)
- def config_attribute(name, options = {})
- if options[:global]
- class_eval <<-CODE, __FILE__, __LINE__ + 1
- def self.#{name}; ActiveRecord::Model.#{name}; end
- def #{name}; ActiveRecord::Model.#{name}; end
- def self.#{name}=(val); ActiveRecord::Model.#{name} = val; end
- CODE
- else
- options[:instance_writer] ||= false
- class_attribute name, options
-
- singleton_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
- remove_method :#{name}
- def #{name}; ActiveRecord::Model.#{name}; end
- CODE
- end
- end
- end
-
- # This allows us to detect an ActiveRecord::Model while it's in the process of
- # being included.
- module Tag; end
-
- # <tt>ActiveRecord::Model</tt> can be included into a class to add Active Record
- # persistence. This is an alternative to inheriting from <tt>ActiveRecord::Base</tt>.
- #
- # class Post
- # include ActiveRecord::Model
- # end
- module Model
- extend ActiveSupport::Concern
- extend ConnectionHandling
- extend ActiveModel::Observing::ClassMethods
-
- def self.append_features(base)
- base.class_eval do
- include Tag
- extend Configuration
- end
-
- super
- end
-
- included do
- extend ActiveModel::Naming
- extend ActiveSupport::Benchmarkable
- extend ActiveSupport::DescendantsTracker
-
- extend QueryCache::ClassMethods
- extend Querying
- extend Translation
- extend DynamicMatchers
- extend Explain
- extend ConnectionHandling
-
- initialize_generated_modules unless self == Base
- end
-
- include Persistence
- include ReadonlyAttributes
- include ModelSchema
- include Inheritance
- include Scoping
- include Sanitization
- include AttributeAssignment
- include ActiveModel::Conversion
- include Integration
- include Validations
- include CounterCache
- include Locking::Optimistic
- include Locking::Pessimistic
- include AttributeMethods
- include Callbacks
- include ActiveModel::Observing
- include Timestamp
- include Associations
- include ActiveModel::SecurePassword
- include AutosaveAssociation
- include NestedAttributes
- include Aggregations
- include Transactions
- include Reflection
- include Serialization
- include Store
- include Core
-
- class << self
- def arel_engine
- self
- end
-
- def abstract_class?
- false
- end
-
- # Defines the name of the table column which will store the class name on single-table
- # inheritance situations.
- #
- # The default inheritance column name is +type+, which means it's a
- # reserved word inside Active Record. To be able to use single-table
- # inheritance with another column name, or to use the column +type+ in
- # your own model for something else, you can set +inheritance_column+:
- #
- # self.inheritance_column = 'zoink'
- def inheritance_column
- 'type'
- end
- end
-
- class DeprecationProxy < BasicObject #:nodoc:
- def initialize(model = Model, base = Base)
- @model = model
- @base = base
- end
-
- def method_missing(name, *args, &block)
- if @model.respond_to?(name, true)
- @model.send(name, *args, &block)
- else
- ::ActiveSupport::Deprecation.warn(
- "The object passed to the active_record load hook was previously ActiveRecord::Base " \
- "(a Class). Now it is ActiveRecord::Model (a Module). You have called `#{name}' which " \
- "is only defined on ActiveRecord::Base. Please change your code so that it works with " \
- "a module rather than a class. (Model is included in Base, so anything added to Model " \
- "will be available on Base as well.)"
- )
- @base.send(name, *args, &block)
- end
- end
-
- alias send method_missing
-
- def extend(*mods)
- ::ActiveSupport::Deprecation.warn(
- "The object passed to the active_record load hook was previously ActiveRecord::Base " \
- "(a Class). Now it is ActiveRecord::Model (a Module). You have called `extend' which " \
- "would add singleton methods to Model. This is presumably not what you want, since the " \
- "methods would not be inherited down to Base. Rather than using extend, please use " \
- "ActiveSupport::Concern + include, which will ensure that your class methods are " \
- "inherited."
- )
- @base.extend(*mods)
- end
- end
- end
-
- # This hook is where config accessors on Model get defined.
- #
- # We don't want to just open the Model module and add stuff to it in other files, because
- # that would cause Model to load, which causes all sorts of loading order issues.
- #
- # We need this hook rather than just using the :active_record one, because users of the
- # :active_record hook may need to use config options.
- ActiveSupport.run_load_hooks(:active_record_config, Model)
-
- # Load Base at this point, because the active_record load hook is run in that file.
- Base
-end
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 99de16cd33..1b95b72c8a 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -1,18 +1,4 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :primary_key_prefix_type, instance_accessor: false
-
- mattr_accessor :table_name_prefix, instance_accessor: false
- self.table_name_prefix = ""
-
- mattr_accessor :table_name_suffix, instance_accessor: false
- self.table_name_suffix = ""
-
- mattr_accessor :pluralize_table_names, instance_accessor: false
- self.pluralize_table_names = true
- end
-
module ModelSchema
extend ActiveSupport::Concern
@@ -24,7 +10,7 @@ module ActiveRecord
# the Product class will look for "productid" instead of "id" as the primary column. If the
# latter is specified, the Product class will look for "product_id" instead of "id". Remember
# that this is a global setting for all Active Records.
- config_attribute :primary_key_prefix_type, global: true
+ mattr_accessor :primary_key_prefix_type, instance_writer: false
##
# :singleton-method:
@@ -36,20 +22,25 @@ module ActiveRecord
# If you are organising your models within modules you can add a prefix to the models within
# a namespace by defining a singleton method in the parent module called table_name_prefix which
# returns your chosen prefix.
- config_attribute :table_name_prefix
+ class_attribute :table_name_prefix, instance_writer: false
+ self.table_name_prefix = ""
##
# :singleton-method:
# Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
# "people_basecamp"). By default, the suffix is the empty string.
- config_attribute :table_name_suffix
+ class_attribute :table_name_suffix, instance_writer: false
+ self.table_name_suffix = ""
##
# :singleton-method:
# Indicates whether table names should be the pluralized versions of the corresponding class names.
# If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
# See table_name for the full rules on table/class naming. This is true, by default.
- config_attribute :pluralize_table_names
+ class_attribute :pluralize_table_names, instance_writer: false
+ self.pluralize_table_names = true
+
+ self.inheritance_column = 'type'
end
module ClassMethods
@@ -144,9 +135,9 @@ module ActiveRecord
# Computes the table name, (re)sets it internally, and returns it.
def reset_table_name #:nodoc:
self.table_name = if abstract_class?
- active_record_super == Base ? nil : active_record_super.table_name
- elsif active_record_super.abstract_class?
- active_record_super.table_name || compute_table_name
+ superclass == Base ? nil : superclass.table_name
+ elsif superclass.abstract_class?
+ superclass.table_name || compute_table_name
else
compute_table_name
end
@@ -156,9 +147,17 @@ module ActiveRecord
(parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
end
- # The name of the column containing the object's class when Single Table Inheritance is used
+ # Defines the name of the table column which will store the class name on single-table
+ # inheritance situations.
+ #
+ # The default inheritance column name is +type+, which means it's a
+ # reserved word inside Active Record. To be able to use single-table
+ # inheritance with another column name, or to use the column +type+ in
+ # your own model for something else, you can set +inheritance_column+:
+ #
+ # self.inheritance_column = 'zoink'
def inheritance_column
- (@inheritance_column ||= nil) || active_record_super.inheritance_column
+ (@inheritance_column ||= nil) || superclass.inheritance_column
end
# Sets the value of inheritance_column
@@ -331,7 +330,7 @@ module ActiveRecord
base = base_class
if self == base
# Nested classes are prefixed with singular parent table name.
- if parent < ActiveRecord::Model && !parent.abstract_class?
+ if parent < Base && !parent.abstract_class?
contained = parent.table_name
contained = contained.singularize if parent.pluralize_table_names
contained += '_'
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 43f908ae5f..aba56c2861 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -3,11 +3,6 @@ require 'active_support/core_ext/object/try'
require 'active_support/core_ext/hash/indifferent_access'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :nested_attributes_options, instance_accessor: false
- self.nested_attributes_options = {}
- end
-
module NestedAttributes #:nodoc:
class TooManyRecords < ActiveRecordError
end
@@ -15,7 +10,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :nested_attributes_options
+ class_attribute :nested_attributes_options, instance_writer: false
+ self.nested_attributes_options = {}
end
# = Active Record Nested Attributes
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 65a31f1566..8e749772a1 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -224,11 +224,13 @@ module ActiveRecord
verify_readonly_attribute(key.to_s)
end
+ updated_count = self.class.where(self.class.primary_key => id).update_all(attributes)
+
attributes.each do |k,v|
raw_write_attribute(k,v)
end
- self.class.where(self.class.primary_key => id).update_all(attributes) == 1
+ updated_count == 1
end
# Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index 2bd8ecda20..38e18b32a4 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -5,19 +5,19 @@ module ActiveRecord
module ClassMethods
# Enable the query cache within the block if Active Record is configured.
def cache(&block)
- if ActiveRecord::Base.configurations.blank?
- yield
- else
+ if ActiveRecord::Base.connected?
connection.cache(&block)
+ else
+ yield
end
end
# Disable the query cache within the block if Active Record is configured.
def uncached(&block)
- if ActiveRecord::Base.configurations.blank?
- yield
- else
+ if ActiveRecord::Base.connected?
connection.uncached(&block)
+ else
+ yield
end
end
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index d7e35fb771..77e41ea927 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -80,7 +80,7 @@ module ActiveRecord
if File.file?(filename)
cache = Marshal.load File.binread filename
if cache.version == ActiveRecord::Migrator.current_version
- ActiveRecord::Model.connection.schema_cache = cache
+ self.connection.schema_cache = cache
else
warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
end
@@ -122,8 +122,8 @@ module ActiveRecord
ActiveSupport.on_load(:active_record) do
ActionDispatch::Reloader.send(hook) do
- ActiveRecord::Model.clear_reloadable_connections!
- ActiveRecord::Model.clear_cache!
+ ActiveRecord::Base.clear_reloadable_connections!
+ ActiveRecord::Base.clear_cache!
end
end
end
@@ -135,13 +135,12 @@ module ActiveRecord
config.after_initialize do |app|
ActiveSupport.on_load(:active_record) do
- ActiveRecord::Model.instantiate_observers
+ instantiate_observers
ActionDispatch::Reloader.to_prepare do
- ActiveRecord::Model.instantiate_observers
+ ActiveRecord::Base.instantiate_observers
end
end
-
end
end
end
diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb
index b3c20c4aff..8499bb16e7 100644
--- a/activerecord/lib/active_record/readonly_attributes.rb
+++ b/activerecord/lib/active_record/readonly_attributes.rb
@@ -22,7 +22,8 @@ module ActiveRecord
end
def _attr_readonly
- ActiveSupport::Deprecation.warn("Instance level _attr_readonly method is deprecated, please use class level method.")
+ message = "Instance level _attr_readonly method is deprecated, please use class level method."
+ ActiveSupport::Deprecation.warn message
defined?(@_attr_readonly) ? @_attr_readonly : self.class._attr_readonly
end
end
diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb
index 8af0c6a8ef..b921f2eddb 100644
--- a/activerecord/lib/active_record/relation/batches.rb
+++ b/activerecord/lib/active_record/relation/batches.rb
@@ -62,11 +62,11 @@ module ActiveRecord
ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size")
end
- start = options.delete(:start) || 0
+ start = options.delete(:start)
batch_size = options.delete(:batch_size) || 1000
relation = relation.reorder(batch_order).limit(batch_size)
- records = relation.where(table[primary_key].gteq(start)).to_a
+ records = start ? relation.where(table[primary_key].gteq(start)).to_a : relation.to_a
while records.any?
records_size = records.size
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 84aaa39fed..99c2f45bc8 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -159,7 +159,7 @@ module ActiveRecord
# Person.exists?(false)
# Person.exists?
def exists?(conditions = :none)
- conditions = conditions.id if ActiveRecord::Model === conditions
+ conditions = conditions.id if Base === conditions
return false if !conditions
join_dependency = construct_join_dependency_for_association_find
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 71030cb5d7..bd7aeb0c4e 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -40,7 +40,7 @@ module ActiveRecord
#
# For polymorphic relationships, find the foreign key and type:
# PriceEstimate.where(:estimate_of => treasure)
- if klass && value.class < ActiveRecord::Tag && reflection = klass.reflect_on_association(column.to_sym)
+ if klass && value.class < Base && reflection = klass.reflect_on_association(column.to_sym)
if reflection.polymorphic?
queries << build(table[reflection.foreign_type], value.class.base_class)
end
@@ -67,7 +67,7 @@ module ActiveRecord
def self.build(attribute, value)
case value
when Array, ActiveRecord::Associations::CollectionProxy
- values = value.to_a.map {|x| x.is_a?(ActiveRecord::Model) ? x.id : x}
+ values = value.to_a.map {|x| x.is_a?(Base) ? x.id : x}
ranges, values = values.partition {|v| v.is_a?(Range)}
values_predicate = if values.include?(nil)
@@ -93,7 +93,7 @@ module ActiveRecord
attribute.in(value.arel.ast)
when Range
attribute.in(value)
- when ActiveRecord::Model
+ when ActiveRecord::Base
attribute.eq(value.id)
when Class
# FIXME: I think we need to deprecate this behavior
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 14bcb337e9..4fdc296c7e 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -496,6 +496,11 @@ module ActiveRecord
extending(NullRelation)
end
+ # Like #none, but modifies relation in place.
+ def none!
+ extending!(NullRelation)
+ end
+
# Sets readonly attributes for the returned relation. If value is
# true (default), attempting to update a record will result in an error.
#
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb
index 425b9b41d8..bea195e9b8 100644
--- a/activerecord/lib/active_record/result.rb
+++ b/activerecord/lib/active_record/result.rb
@@ -56,7 +56,7 @@ module ActiveRecord
@hash_rows ||=
begin
# We freeze the strings to prevent them getting duped when
- # used as keys in ActiveRecord::Model's @attributes hash
+ # used as keys in ActiveRecord::Base's @attributes hash
columns = @columns.map { |c| c.dup.freeze }
@rows.map { |row|
Hash[columns.zip(row)]
diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb
index e8dd312a47..6b55af4205 100644
--- a/activerecord/lib/active_record/serialization.rb
+++ b/activerecord/lib/active_record/serialization.rb
@@ -1,19 +1,11 @@
module ActiveRecord #:nodoc:
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :include_root_in_json, instance_accessor: false
- self.include_root_in_json = true
- end
-
# = Active Record Serialization
module Serialization
extend ActiveSupport::Concern
include ActiveModel::Serializers::JSON
included do
- singleton_class.class_eval do
- remove_method :include_root_in_json
- delegate :include_root_in_json, to: 'ActiveRecord::Model'
- end
+ self.include_root_in_json = true
end
def serializable_hash(options = nil)
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index ec4588f601..920d6848c1 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -1,8 +1,6 @@
module ActiveRecord
ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :record_timestamps, instance_accessor: false
- self.record_timestamps = true
end
# = Active Record Timestamp
@@ -37,7 +35,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :record_timestamps, instance_writer: true
+ class_attribute :record_timestamps
+ self.record_timestamps = true
end
def initialize_dup(other) # :nodoc:
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 934393b4e7..f91abfbd19 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -328,6 +328,7 @@ module ActiveRecord
@_start_transaction_state[:new_record] = @new_record
@_start_transaction_state[:destroyed] = @destroyed
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
+ @_start_transaction_state[:frozen?] = @attributes.frozen?
end
# Clear the new record state and id of a record.
@@ -342,8 +343,8 @@ module ActiveRecord
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
if @_start_transaction_state[:level] < 1 || force
restore_state = @_start_transaction_state
- was_frozen = @attributes.frozen?
- @attributes = @attributes.dup if was_frozen
+ was_frozen = restore_state[:frozen?]
+ @attributes = @attributes.dup if @attributes.frozen?
@new_record = restore_state[:new_record]
@destroyed = restore_state[:destroyed]
if restore_state.has_key?(:id)
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 93b01a3934..404b492288 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -69,16 +69,16 @@ module ActiveRecord
def test_not_specifying_database_name_for_cross_database_selects
begin
assert_nothing_raised do
- ActiveRecord::Model.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
config = ARTest.connection_config
- ActiveRecord::Model.connection.execute(
+ ActiveRecord::Base.connection.execute(
"SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
"FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
)
end
ensure
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.establish_connection 'arunit'
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb
index 4bccd2cc59..534dc2c2df 100644
--- a/activerecord/test/cases/adapters/mysql/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql/connection_test.rb
@@ -3,13 +3,13 @@ require "cases/helper"
class MysqlConnectionTest < ActiveRecord::TestCase
def setup
super
- @connection = ActiveRecord::Model.connection
+ @connection = ActiveRecord::Base.connection
end
def test_mysql_reconnect_attribute_after_connection_with_reconnect_true
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => true}))
- assert ActiveRecord::Model.connection.raw_connection.reconnect
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true}))
+ assert ActiveRecord::Base.connection.raw_connection.reconnect
end
end
@@ -25,8 +25,8 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_reconnect_attribute_after_connection_with_reconnect_false
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => false}))
- assert !ActiveRecord::Model.connection.raw_connection.reconnect
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => false}))
+ assert !ActiveRecord::Base.connection.raw_connection.reconnect
end
end
@@ -117,7 +117,7 @@ class MysqlConnectionTest < ActiveRecord::TestCase
# Test that MySQL allows multiple results for stored procedures
if defined?(Mysql) && Mysql.const_defined?(:CLIENT_MULTI_RESULTS)
def test_multi_results
- rows = ActiveRecord::Model.connection.select_rows('CALL ten();')
+ rows = ActiveRecord::Base.connection.select_rows('CALL ten();')
assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
assert @connection.active?, "Bad connection use by 'MysqlAdapter.select_rows'"
end
@@ -130,9 +130,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_strict_mode_disabled_dont_override_global_sql_mode
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false}))
- global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode"
- session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode"
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false}))
+ global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode"
+ session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
assert_equal global_sql_mode.rows, session_sql_mode.rows
end
end
@@ -140,11 +140,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Model.remove_connection
+ original_connection = ActiveRecord::Base.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Model.establish_connection(original_connection)
+ ActiveRecord::Base.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql/sql_types_test.rb b/activerecord/test/cases/adapters/mysql/sql_types_test.rb
new file mode 100644
index 0000000000..1ddb1b91c9
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql/sql_types_test.rb
@@ -0,0 +1,14 @@
+require "cases/helper"
+
+class SqlTypesTest < ActiveRecord::TestCase
+ def test_binary_types
+ assert_equal 'varbinary(64)', type_to_sql(:binary, 64)
+ assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095)
+ assert_equal 'blob(4096)', type_to_sql(:binary, 4096)
+ assert_equal 'blob', type_to_sql(:binary)
+ end
+
+ def type_to_sql(*args)
+ ActiveRecord::Base.connection.type_to_sql(*args)
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index c63e4fe5b6..14c22d2519 100644
--- a/activerecord/test/cases/adapters/mysql2/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -3,7 +3,7 @@ require "cases/helper"
class MysqlConnectionTest < ActiveRecord::TestCase
def setup
super
- @connection = ActiveRecord::Model.connection
+ @connection = ActiveRecord::Base.connection
@connection.extend(LogIntercepter)
@connection.intercepted = true
end
@@ -46,9 +46,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_strict_mode_disabled_dont_override_global_sql_mode
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false}))
- global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode"
- session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode"
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false}))
+ global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode"
+ session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
assert_equal global_sql_mode.rows, session_sql_mode.rows
end
end
@@ -76,11 +76,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Model.remove_connection
+ original_connection = ActiveRecord::Base.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Model.establish_connection(original_connection)
+ ActiveRecord::Base.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/sql_types_test.rb b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb
new file mode 100644
index 0000000000..1ddb1b91c9
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb
@@ -0,0 +1,14 @@
+require "cases/helper"
+
+class SqlTypesTest < ActiveRecord::TestCase
+ def test_binary_types
+ assert_equal 'varbinary(64)', type_to_sql(:binary, 64)
+ assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095)
+ assert_equal 'blob(4096)', type_to_sql(:binary, 4096)
+ assert_equal 'blob', type_to_sql(:binary)
+ end
+
+ def type_to_sql(*args)
+ ActiveRecord::Base.connection.type_to_sql(*args)
+ end
+end
diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
index 74288a98d1..d03d1dd94c 100644
--- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
@@ -32,6 +32,11 @@ class CopyTableTest < ActiveRecord::TestCase
end
end
+ def test_copy_table_allows_to_pass_options_to_create_table
+ @connection.create_table('blocker_table')
+ test_copy_table('customers', 'blocker_table', force: true)
+ end
+
def test_copy_table_with_index
test_copy_table('comments', 'comments_with_index') do
@connection.add_index('comments_with_index', ['post_id', 'type'])
@@ -43,7 +48,9 @@ class CopyTableTest < ActiveRecord::TestCase
end
def test_copy_table_without_primary_key
- test_copy_table('developers_projects', 'programmers_projects')
+ test_copy_table('developers_projects', 'programmers_projects') do
+ assert_nil @connection.primary_key('programmers_projects')
+ end
end
def test_copy_table_with_id_col_that_is_not_primary_key
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 4e26c5dda1..003052bac4 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -154,6 +154,12 @@ module ActiveRecord
DualEncoding.connection.drop_table('dual_encodings')
end
+ def test_type_cast_should_not_mutate_encoding
+ name = 'hello'.force_encoding(Encoding::ASCII_8BIT)
+ Owner.create(name: name)
+ assert_equal Encoding::ASCII_8BIT, name.encoding
+ end
+
def test_execute
@conn.execute "INSERT INTO items (number) VALUES (10)"
records = @conn.execute "SELECT * FROM items"
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index aad48e7ce9..8c9b4fb921 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -261,10 +261,23 @@ class InverseHasManyTests < ActiveRecord::TestCase
def test_parent_instance_should_be_shared_with_first_and_last_child
man = Man.first
+
assert man.interests.first.man.equal? man
assert man.interests.last.man.equal? man
end
+ def test_parent_instance_should_be_shared_with_first_n_and_last_n_children
+ man = Man.first
+
+ interests = man.interests.first(2)
+ assert interests[0].man.equal? man
+ assert interests[1].man.equal? man
+
+ interests = man.interests.last(2)
+ assert interests[0].man.equal? man
+ assert interests[1].man.equal? man
+ end
+
def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.first.secret_interests }
end
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index da5d9d8c2a..8d8ff2f952 100644
--- a/activerecord/test/cases/attribute_methods/read_test.rb
+++ b/activerecord/test/cases/attribute_methods/read_test.rb
@@ -11,10 +11,8 @@ module ActiveRecord
def setup
@klass = Class.new do
def self.superclass; Base; end
- def self.active_record_super; Base; end
def self.base_class; self; end
- extend ActiveRecord::Configuration
include ActiveRecord::AttributeMethods
def self.define_attribute_methods
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index c2b58fd7d1..8b82b79219 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -287,6 +287,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "Don't change the topic", topic[:title]
end
+ def test_read_attribute_raises_missing_attribute_error_when_not_exists
+ computer = Computer.select('id').first
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
+ end
+
def test_read_attribute_when_false
topic = topics(:first)
topic.approved = false
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 0f859bf452..203e44857a 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -23,7 +23,6 @@ require 'models/edge'
require 'models/joke'
require 'models/bulb'
require 'models/bird'
-require 'models/teapot'
require 'rexml/document'
require 'active_support/core_ext/exception'
@@ -1196,10 +1195,6 @@ class BasicsTest < ActiveRecord::TestCase
# Concrete subclasses an abstract class which has a type column.
assert !SubStiPost.descends_from_active_record?
-
- assert Teapot.descends_from_active_record?
- assert !OtherTeapot.descends_from_active_record?
- assert CoolTeapot.descends_from_active_record?
end
def test_find_on_abstract_base_class_doesnt_use_type_condition
@@ -1453,15 +1448,6 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal scope, Bird.uniq
end
- def test_active_record_super
- assert_equal ActiveRecord::Model, ActiveRecord::Base.active_record_super
- assert_equal ActiveRecord::Base, Topic.active_record_super
- assert_equal Topic, ImportantTopic.active_record_super
- assert_equal ActiveRecord::Model, Teapot.active_record_super
- assert_equal Teapot, OtherTeapot.active_record_super
- assert_equal ActiveRecord::Model, CoolTeapot.active_record_super
- end
-
def test_table_name_with_2_abstract_subclasses
assert_equal "photos", Photo.table_name
end
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 12d5245fbd..acb8b5f562 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -136,4 +136,12 @@ class EachTest < ActiveRecord::TestCase
assert_equal nick_order_subscribers[1..-1].map(&:id), subscribers.map(&:id)
end
+
+ def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified
+ assert_queries(Subscriber.count + 1) do
+ Subscriber.find_each(:batch_size => 1) do |subscriber|
+ assert_kind_of Subscriber, subscriber
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb
index a7b63d15c9..2124c256fa 100644
--- a/activerecord/test/cases/column_test.rb
+++ b/activerecord/test/cases/column_test.rb
@@ -33,6 +33,8 @@ module ActiveRecord
assert_equal 0, column.type_cast('bad1')
assert_equal 0, column.type_cast('bad')
assert_equal 1, column.type_cast(1.7)
+ assert_equal 0, column.type_cast(false)
+ assert_equal 1, column.type_cast(true)
assert_nil column.type_cast(nil)
end
@@ -41,11 +43,9 @@ module ActiveRecord
assert_raises(NoMethodError) do
column.type_cast([])
end
+
assert_raises(NoMethodError) do
- column.type_cast(true)
- end
- assert_raises(NoMethodError) do
- column.type_cast(false)
+ column.type_cast(Object.new)
end
end
diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
index 4467ddfc39..631bf1aaac 100644
--- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb
+++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -4,8 +4,8 @@ module ActiveRecord
module ConnectionAdapters
class ConnectionHandlerTest < ActiveRecord::TestCase
def setup
- @klass = Class.new { include ActiveRecord::Tag }
- @subklass = Class.new(@klass) { include ActiveRecord::Tag }
+ @klass = Class.new(Base)
+ @subklass = Class.new(@klass)
@handler = ConnectionHandler.new
@handler.establish_connection @klass, Base.connection_pool.spec
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index 434d2b7ba5..ee9818678d 100644
--- a/activerecord/test/cases/connection_specification/resolver_test.rb
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -9,7 +9,7 @@ module ActiveRecord
end
def test_url_host_no_db
- skip "only if mysql is available" unless defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
spec = resolve 'mysql://foo?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -18,7 +18,7 @@ module ActiveRecord
end
def test_url_host_db
- skip "only if mysql is available" unless defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
spec = resolve 'mysql://foo/bar?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -28,7 +28,7 @@ module ActiveRecord
end
def test_url_port
- skip "only if mysql is available" unless defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
spec = resolve 'mysql://foo:123?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -36,6 +36,14 @@ module ActiveRecord
:host => "foo",
:encoding => "utf8" }, spec)
end
+
+ def test_encoded_password
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ password = 'am@z1ng_p@ssw0rd#!'
+ encoded_password = URI.encode_www_form_component(password)
+ spec = resolve "mysql://foo:#{encoded_password}@localhost/bar"
+ assert_equal password, spec[:password]
+ end
end
end
end
diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb
index 0df872ff10..ed7eedaa27 100644
--- a/activerecord/test/cases/defaults_test.rb
+++ b/activerecord/test/cases/defaults_test.rb
@@ -52,12 +52,12 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
self.use_transactional_fixtures = false
def using_strict(strict)
- connection = ActiveRecord::Model.remove_connection
- ActiveRecord::Model.establish_connection connection.merge(strict: strict)
+ connection = ActiveRecord::Base.remove_connection
+ ActiveRecord::Base.establish_connection connection.merge(strict: strict)
yield
ensure
- ActiveRecord::Model.remove_connection
- ActiveRecord::Model.establish_connection connection
+ ActiveRecord::Base.remove_connection
+ ActiveRecord::Base.establish_connection connection
end
# MySQL cannot have defaults on text/blob columns. It reports the
diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb
deleted file mode 100644
index 8f095e4953..0000000000
--- a/activerecord/test/cases/inclusion_test.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'cases/helper'
-require 'models/teapot'
-
-class BasicInclusionModelTest < ActiveRecord::TestCase
- def test_basic_model
- Teapot.create!(:name => "Ronnie Kemper")
- assert_equal "Ronnie Kemper", Teapot.first.name
- end
-
- def test_initialization
- t = Teapot.new(:name => "Bob")
- assert_equal "Bob", t.name
- end
-
- def test_inherited_model
- teapot = CoolTeapot.create!(:name => "Bob")
- teapot.reload
-
- assert_equal "Bob", teapot.name
- assert_equal "mmm", teapot.aaahhh
- end
-
- def test_generated_feature_methods
- assert Teapot < Teapot::GeneratedFeatureMethods
- end
-
- def test_exists
- t = Teapot.create!(:name => "Ronnie Kemper")
- assert Teapot.exists?(t)
- end
-
- def test_predicate_builder
- t = Teapot.create!(:name => "Bob")
- assert_equal "Bob", Teapot.where(:id => [t]).first.name
- assert_equal "Bob", Teapot.where(:id => t).first.name
- end
-
- def test_nested_model
- assert_equal "ceiling_teapots", Ceiling::Teapot.table_name
- end
-end
-
-class InclusionUnitTest < ActiveRecord::TestCase
- def setup
- @klass = Class.new { include ActiveRecord::Model }
- end
-
- def test_non_abstract_class
- assert !@klass.abstract_class?
- end
-
- def test_abstract_class
- @klass.abstract_class = true
- assert @klass.abstract_class?
- end
-
- def test_establish_connection
- assert @klass.respond_to?(:establish_connection)
- assert ActiveRecord::Model.respond_to?(:establish_connection)
- end
-
- def test_adapter_connection
- name = "#{ActiveRecord::Base.connection_config[:adapter]}_connection"
- assert @klass.respond_to?(name)
- assert ActiveRecord::Model.respond_to?(name)
- end
-
- def test_connection_handler
- assert_equal ActiveRecord::Base.connection_handler, @klass.connection_handler
- end
-
- def test_mirrored_configuration
- ActiveRecord::Base.time_zone_aware_attributes = true
- assert @klass.time_zone_aware_attributes
- ActiveRecord::Base.time_zone_aware_attributes = false
- assert !@klass.time_zone_aware_attributes
- ensure
- ActiveRecord::Base.time_zone_aware_attributes = false
- end
-
- # Doesn't really test anything, but this is here to ensure warnings don't occur
- def test_included_twice
- @klass.send :include, ActiveRecord::Model
- end
-
- def test_deprecation_proxy
- proxy = ActiveRecord::Model::DeprecationProxy.new
-
- assert_equal ActiveRecord::Model.name, proxy.name
- assert_equal ActiveRecord::Base.superclass, assert_deprecated { proxy.superclass }
-
- sup, sup2 = nil, nil
- ActiveSupport.on_load(:__test_active_record_model_deprecation) do
- sup = superclass
- sup2 = send(:superclass)
- end
- assert_deprecated do
- ActiveSupport.run_load_hooks(:__test_active_record_model_deprecation, proxy)
- end
- assert_equal ActiveRecord::Base.superclass, sup
- assert_equal ActiveRecord::Base.superclass, sup2
- end
-
- test "including in deprecation proxy" do
- model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup
- proxy = ActiveRecord::Model::DeprecationProxy.new(model, base)
-
- mod = Module.new
- proxy.include mod
- assert model < mod
- end
-
- test "extending in deprecation proxy" do
- model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup
- proxy = ActiveRecord::Model::DeprecationProxy.new(model, base)
-
- mod = Module.new
- assert_deprecated { proxy.extend mod }
- assert base.singleton_class < mod
- end
-end
-
-class InclusionFixturesTest < ActiveRecord::TestCase
- fixtures :teapots
-
- def test_fixtured_record
- assert_equal "Bob", teapots(:bob).name
- end
-
- def test_timestamped_fixture
- assert_not_nil teapots(:bob).created_at
- end
-end
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 8fded9159f..aab7aa51dd 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -4,7 +4,6 @@ require 'models/person'
require 'models/post'
require 'models/project'
require 'models/subscriber'
-require 'models/teapot'
require 'models/vegetables'
class InheritanceTest < ActiveRecord::TestCase
@@ -81,10 +80,6 @@ class InheritanceTest < ActiveRecord::TestCase
assert_equal SubStiPost, SubStiPost.base_class
end
- def test_active_record_model_included_base_class
- assert_equal Teapot, Teapot.base_class
- end
-
def test_abstract_inheritance_base_class
assert_equal LoosePerson, LoosePerson.base_class
assert_equal LooseDescendant, LooseDescendant.base_class
@@ -93,11 +88,7 @@ class InheritanceTest < ActiveRecord::TestCase
end
def test_base_class_activerecord_error
- klass = Class.new {
- extend ActiveRecord::Configuration
- include ActiveRecord::Inheritance
- }
-
+ klass = Class.new { include ActiveRecord::Inheritance }
assert_raise(ActiveRecord::ActiveRecordError) { klass.base_class }
end
diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb
index 17c1634444..86451289e7 100644
--- a/activerecord/test/cases/migration/change_schema_test.rb
+++ b/activerecord/test/cases/migration/change_schema_test.rb
@@ -132,6 +132,26 @@ module ActiveRecord
assert_equal %w(foo testingid), connection.columns(:testings).map(&:name).sort
end
+ def test_create_table_raises_when_redefining_primary_key_column
+ error = assert_raise(ArgumentError) do
+ connection.create_table :testings do |t|
+ t.column :id, :string
+ end
+ end
+
+ assert_equal "you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table.", error.message
+ end
+
+ def test_create_table_raises_when_redefining_custom_primary_key_column
+ error = assert_raise(ArgumentError) do
+ connection.create_table :testings, primary_key: :testing_id do |t|
+ t.column :testing_id, :string
+ end
+ end
+
+ assert_equal "you can't redefine the primary key column 'testing_id'. To define a custom primary key, pass { id: false } to create_table.", error.message
+ end
+
def test_create_table_with_timestamps_should_create_datetime_columns
connection.create_table table_name do |t|
t.timestamps
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index 42461e8ecb..2e386a172a 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -96,12 +96,12 @@ class MultipleDbTest < ActiveRecord::TestCase
unless in_memory_db?
def test_associations_should_work_when_model_has_no_connection
begin
- ActiveRecord::Model.remove_connection
+ ActiveRecord::Base.remove_connection
assert_nothing_raised ActiveRecord::ConnectionNotEstablished do
College.first.courses.first
end
ensure
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.establish_connection 'arunit'
end
end
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index b5f32a57b2..4b938da5c4 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -592,6 +592,19 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal 'super_title', t.title
end
+ def test_update_columns_changing_id
+ topic = Topic.find(1)
+ topic.update_columns(id: 123)
+ assert_equal 123, topic.id
+ topic.reload
+ assert_equal 123, topic.id
+ end
+
+ def test_update_columns_returns_boolean
+ topic = Topic.find(1)
+ assert_equal true, topic.update_columns(title: "New title")
+ end
+
def test_update_attributes
topic = Topic.find(1)
assert !topic.approved?
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 0a6354f5cc..a8a9b06ec4 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -7,17 +7,17 @@ class PooledConnectionsTest < ActiveRecord::TestCase
def setup
@per_test_teardown = []
- @connection = ActiveRecord::Model.remove_connection
+ @connection = ActiveRecord::Base.remove_connection
end
def teardown
- ActiveRecord::Model.clear_all_connections!
- ActiveRecord::Model.establish_connection(@connection)
+ ActiveRecord::Base.clear_all_connections!
+ ActiveRecord::Base.establish_connection(@connection)
@per_test_teardown.each {|td| td.call }
end
def checkout_connections
- ActiveRecord::Model.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3}))
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3}))
@connections = []
@timed_out = 0
@@ -34,15 +34,15 @@ class PooledConnectionsTest < ActiveRecord::TestCase
# Will deadlock due to lack of Monitor timeouts in 1.9
def checkout_checkin_connections(pool_size, threads)
- ActiveRecord::Model.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5}))
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5}))
@connection_count = 0
@timed_out = 0
threads.times do
Thread.new do
begin
- conn = ActiveRecord::Model.connection_pool.checkout
+ conn = ActiveRecord::Base.connection_pool.checkout
sleep 0.1
- ActiveRecord::Model.connection_pool.checkin conn
+ ActiveRecord::Base.connection_pool.checkin conn
@connection_count += 1
rescue ActiveRecord::ConnectionTimeoutError
@timed_out += 1
@@ -55,13 +55,13 @@ class PooledConnectionsTest < ActiveRecord::TestCase
checkout_checkin_connections 1, 2
assert_equal 2, @connection_count
assert_equal 0, @timed_out
- assert_equal 1, ActiveRecord::Model.connection_pool.connections.size
+ assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
end
private
def add_record(name)
- ActiveRecord::Model.connection_pool.with_connection { Project.create! :name => name }
+ ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
end
end unless current_adapter?(:FrontBase) || in_memory_db?
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index e6e50a4cd4..bf8aacc363 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -188,14 +188,14 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
def test_set_primary_key_with_no_connection
return skip("disconnect wipes in-memory db") if in_memory_db?
- connection = ActiveRecord::Model.remove_connection
+ connection = ActiveRecord::Base.remove_connection
model = Class.new(ActiveRecord::Base)
model.primary_key = 'foo'
assert_equal 'foo', model.primary_key
- ActiveRecord::Model.establish_connection(connection)
+ ActiveRecord::Base.establish_connection(connection)
assert_equal 'foo', model.primary_key
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 51a285a2b4..4ff481e6a5 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -184,6 +184,17 @@ class QueryCacheTest < ActiveRecord::TestCase
assert_queries(2) { task.lock!; task.lock! }
end
end
+
+ def test_cache_is_available_when_connection_is_connected
+ conf = ActiveRecord::Base.configurations
+
+ ActiveRecord::Base.configurations = {}
+ Task.cache do
+ assert_queries(1) { Task.find(1); Task.find(1) }
+ end
+ ensure
+ ActiveRecord::Base.configurations = conf
+ end
end
class QueryCacheExpiryTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 6399111be6..98e278df82 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -256,5 +256,11 @@ module ActiveRecord
test 'merge with a proc' do
assert_equal [:foo], relation.merge(-> { where(:foo) }).where_values
end
+
+ test 'none!' do
+ assert relation.none!.equal?(relation)
+ assert_equal [NullRelation], relation.extending_values
+ assert relation.is_a?(NullRelation)
+ end
end
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 5f96145b47..bc6cac0c6c 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1391,6 +1391,15 @@ class RelationTest < ActiveRecord::TestCase
end
end
+ test "loaded relations cannot be mutated by extending!" do
+ relation = Post.all
+ relation.to_a
+
+ assert_raises(ActiveRecord::ImmutableRelation) do
+ relation.extending! Module.new
+ 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
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 5f13124e5b..7ff0044bd4 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -203,6 +203,12 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t.text\s+"body",\s+null: false$}, output
end
+ def test_schema_dump_includes_length_for_mysql_binary_fields
+ output = standard_dump
+ assert_match %r{t.binary\s+"var_binary",\s+limit: 255$}, output
+ assert_match %r{t.binary\s+"var_binary_large",\s+limit: 4095$}, output
+ end
+
def test_schema_dump_includes_length_for_mysql_blob_and_text_fields
output = standard_dump
assert_match %r{t.binary\s+"tiny_blob",\s+limit: 255$}, output
diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb
index 25b860878a..eb9cb91e32 100644
--- a/activerecord/test/cases/serialization_test.rb
+++ b/activerecord/test/cases/serialization_test.rb
@@ -45,4 +45,20 @@ class SerializationTest < ActiveRecord::TestCase
assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}"
end
end
+
+ def test_include_root_in_json_allows_inheritance
+ original_root_in_json = ActiveRecord::Base.include_root_in_json
+ ActiveRecord::Base.include_root_in_json = true
+
+ klazz = Class.new(ActiveRecord::Base)
+ klazz.table_name = 'topics'
+ assert klazz.include_root_in_json
+
+ klazz.include_root_in_json = false
+ assert ActiveRecord::Base.include_root_in_json
+ assert !klazz.include_root_in_json
+ assert !klazz.new.include_root_in_json
+ ensure
+ ActiveRecord::Base.include_root_in_json = original_root_in_json
+ end
end
diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb
index f24ee54cd2..068f3cf3cd 100644
--- a/activerecord/test/cases/serialized_attribute_test.rb
+++ b/activerecord/test/cases/serialized_attribute_test.rb
@@ -56,11 +56,21 @@ class SerializedAttributeTest < ActiveRecord::TestCase
def test_serialized_attribute_before_type_cast_returns_unserialized_value
Topic.serialize :content, Hash
- t = Topic.new(:content => { :foo => :bar })
- assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ t = Topic.new(content: { foo: :bar })
+ assert_equal({ foo: :bar }, t.content_before_type_cast)
t.save!
t.reload
- assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ assert_equal({ foo: :bar }, t.content_before_type_cast)
+ end
+
+ def test_serialized_attributes_before_type_cast_returns_unserialized_value
+ Topic.serialize :content, Hash
+
+ t = Topic.new(content: { foo: :bar })
+ assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"])
+ t.save!
+ t.reload
+ assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"])
end
def test_serialized_attribute_calling_dup_method
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index bb4f2c8064..fdca10f4fb 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -14,6 +14,21 @@ class TransactionTest < ActiveRecord::TestCase
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
end
+ def test_raise_after_destroy
+ refute @first.frozen?
+
+ assert_raises(RuntimeError) {
+ Topic.transaction do
+ @first.destroy
+ assert @first.frozen?
+ raise
+ end
+ }
+
+ assert @first.reload
+ refute @first.frozen?
+ end
+
def test_successful
Topic.transaction do
@first.approved = true
diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb
index 5a69054445..e82ca3f93d 100644
--- a/activerecord/test/cases/unconnected_test.rb
+++ b/activerecord/test/cases/unconnected_test.rb
@@ -7,13 +7,13 @@ class TestUnconnectedAdapter < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
- @underlying = ActiveRecord::Model.connection
- @specification = ActiveRecord::Model.remove_connection
+ @underlying = ActiveRecord::Base.connection
+ @specification = ActiveRecord::Base.remove_connection
end
def teardown
@underlying = nil
- ActiveRecord::Model.establish_connection(@specification)
+ ActiveRecord::Base.establish_connection(@specification)
load_schema if in_memory_db?
end
diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
index 174d96aa4e..32d2bf746f 100644
--- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -59,4 +59,18 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
end
+ test "translation for 'taken' can be overridden in activerecord scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {messages: {taken: "Custom taken message" }}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
+
+ test "translation for 'taken' can be overridden in activerecord model scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {taken: "Custom taken message" }}}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
+
+ test "translation for 'taken' can be overridden in activerecord attributes scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {attributes: {title: {taken: "Custom taken message" }}}}}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
end
diff --git a/activerecord/test/models/teapot.rb b/activerecord/test/models/teapot.rb
deleted file mode 100644
index b035b18c1b..0000000000
--- a/activerecord/test/models/teapot.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-class Teapot
- # I'm a little teapot,
- # Short and stout,
- # Here is my handle
- # Here is my spout
- # When I get all steamed up,
- # Hear me shout,
- # Tip me over and pour me out!
- #
- # HELL YEAH TEAPOT SONG
-
- include ActiveRecord::Model
-end
-
-class OtherTeapot < Teapot
-end
-
-class OMFGIMATEAPOT
- def aaahhh
- "mmm"
- end
-end
-
-class CoolTeapot < OMFGIMATEAPOT
- include ActiveRecord::Model
- self.table_name = "teapots"
-end
-
-class Ceiling
- include ActiveRecord::Model
-
- class Teapot
- include ActiveRecord::Model
- end
-end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index 24a43d7ece..f25f72c481 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -1,15 +1,19 @@
ActiveRecord::Schema.define do
- create_table :binary_fields, :force => true do |t|
- t.binary :tiny_blob, :limit => 255
- t.binary :normal_blob, :limit => 65535
- t.binary :medium_blob, :limit => 16777215
- t.binary :long_blob, :limit => 2147483647
- t.text :tiny_text, :limit => 255
- t.text :normal_text, :limit => 65535
- t.text :medium_text, :limit => 16777215
- t.text :long_text, :limit => 2147483647
+ create_table :binary_fields, force: true do |t|
+ t.binary :var_binary, limit: 255
+ t.binary :var_binary_large, limit: 4095
+ t.column :tiny_blob, 'tinyblob', limit: 255
+ t.binary :normal_blob, limit: 65535
+ t.binary :medium_blob, limit: 16777215
+ t.binary :long_blob, limit: 2147483647
+ t.text :tiny_text, limit: 255
+ t.text :normal_text, limit: 65535
+ t.text :medium_text, limit: 16777215
+ t.text :long_text, limit: 2147483647
end
+ add_index :binary_fields, :var_binary
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index 802c08b819..5401c12ed5 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -1,15 +1,19 @@
ActiveRecord::Schema.define do
- create_table :binary_fields, :force => true do |t|
- t.binary :tiny_blob, :limit => 255
- t.binary :normal_blob, :limit => 65535
- t.binary :medium_blob, :limit => 16777215
- t.binary :long_blob, :limit => 2147483647
- t.text :tiny_text, :limit => 255
- t.text :normal_text, :limit => 65535
- t.text :medium_text, :limit => 16777215
- t.text :long_text, :limit => 2147483647
+ create_table :binary_fields, force: true do |t|
+ t.binary :var_binary, limit: 255
+ t.binary :var_binary_large, limit: 4095
+ t.column :tiny_blob, 'tinyblob', limit: 255
+ t.binary :normal_blob, limit: 65535
+ t.binary :medium_blob, limit: 16777215
+ t.binary :long_blob, limit: 2147483647
+ t.text :tiny_text, limit: 255
+ t.text :normal_text, limit: 65535
+ t.text :medium_text, limit: 16777215
+ t.text :long_text, limit: 2147483647
end
+ add_index :binary_fields, :var_binary
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 2e4ec96933..eec06754a5 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -648,12 +648,6 @@ ActiveRecord::Schema.define do
t.datetime :ending
end
- create_table :teapots, :force => true do |t|
- t.string :name
- t.string :type
- t.timestamps
- end
-
create_table :topics, :force => true do |t|
t.string :title
t.string :author_name
diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb
index bea894a583..196b3a9493 100644
--- a/activerecord/test/support/connection.rb
+++ b/activerecord/test/support/connection.rb
@@ -13,9 +13,9 @@ module ARTest
def self.connect
puts "Using #{connection_name}"
- ActiveRecord::Model.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024)
- ActiveRecord::Model.configurations = connection_config
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024)
+ ActiveRecord::Base.configurations = connection_config
+ ActiveRecord::Base.establish_connection 'arunit'
ARUnit2Model.establish_connection 'arunit2'
end
end