mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Remove ActiveRecord::Model
In the end I think the pain of implementing this seamlessly was not worth the gain provided. The intention was that it would allow plain ruby objects that might not live in your main application to be subclassed and have persistence mixed in. But I've decided that the benefit of doing that is not worth the amount of complexity that the implementation introduced.
This commit is contained in:
parent
a27b5178d9
commit
9e4c41c903
40 changed files with 233 additions and 643 deletions
|
@ -926,34 +926,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*
|
||||
|
|
|
@ -43,7 +43,6 @@ module ActiveRecord
|
|||
autoload :Integration
|
||||
autoload :Migration
|
||||
autoload :Migrator, 'active_record/migration'
|
||||
autoload :Model
|
||||
autoload :ModelSchema
|
||||
autoload :NestedAttributes
|
||||
autoload :Observer
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -79,8 +76,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)).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
end
|
||||
extend ActiveModel::Observing::ClassMethods
|
||||
extend ActiveModel::Naming
|
||||
|
||||
ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Model::DeprecationProxy.new)
|
||||
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
|
||||
|
||||
ActiveSupport.run_load_hooks(:active_record, Base)
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module ActiveRecord
|
||||
module ConnectionHandling
|
||||
# Establishes the connection to the database. Accepts a hash as input where
|
||||
|
|
|
@ -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,71 @@ 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
|
||||
|
||||
%w(logger configurations default_timezone schema_format timestamped_migrations).each do |name|
|
||||
config_attribute name, global: true
|
||||
end
|
||||
##
|
||||
# :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 = {}
|
||||
|
||||
##
|
||||
# :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
|
||||
|
||||
mattr_accessor :dependent_restrict_raises, instance_writer: false
|
||||
self.dependent_restrict_raises = true
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
@ -139,7 +131,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
|
@ -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 += '_'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
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
|
||||
mattr_accessor :include_root_in_json, instance_accessor: false
|
||||
self.include_root_in_json = true
|
||||
end
|
||||
|
||||
def serializable_hash(options = nil)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue