diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 360b1218e6..4d143146d5 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -57,6 +57,7 @@ module ActiveRecord autoload :Base autoload :Callbacks + autoload :Configuration autoload :Core autoload :CounterCache autoload :DynamicMatchers diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 1548114580..7d2d1db4b5 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -5,10 +5,7 @@ module ActiveRecord ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date] - included do - cattr_accessor :attribute_types_cached_by_default, :instance_writer => false - self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT - end + Configuration.define :attribute_types_cached_by_default, ATTRIBUTE_TYPES_CACHED_BY_DEFAULT module ClassMethods # +cache_attributes+ allows you to declare which converted attribute values should 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 17cf34cdf6..5e5392441b 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -6,10 +6,9 @@ module ActiveRecord module TimeZoneConversion extend ActiveSupport::Concern - included do - cattr_accessor :time_zone_aware_attributes, :instance_writer => false - self.time_zone_aware_attributes = false + Configuration.define :time_zone_aware_attributes, false + included do class_attribute :skip_time_zone_conversion_for_attributes, :instance_writer => false self.skip_time_zone_conversion_for_attributes = [] end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index e461e2ecc6..7b5544a9cb 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -328,7 +328,6 @@ module ActiveRecord #:nodoc: # instances in the current object space. class Base include ActiveRecord::Model - self.connection_handler = ConnectionAdapters::ConnectionHandler.new end end diff --git a/activerecord/lib/active_record/configuration.rb b/activerecord/lib/active_record/configuration.rb new file mode 100644 index 0000000000..d58ed82258 --- /dev/null +++ b/activerecord/lib/active_record/configuration.rb @@ -0,0 +1,36 @@ +require 'active_support/concern' + +module ActiveRecord + # This module allows configuration options to be specified in a way such that + # ActiveRecord::Base and ActiveRecord::Model will have access to the same value, + # and will automatically get the appropriate readers and writers defined. + # + # In the future, we should probably move away from defining global config + # directly on ActiveRecord::Base / ActiveRecord::Model. + module Configuration #:nodoc: + extend ActiveSupport::Concern + + module ClassMethods + end + + def self.define(name, default = nil) + singleton_class.send(:attr_accessor, name) + + [self, ClassMethods].each do |klass| + klass.class_eval <<-CODE, __FILE__, __LINE__ + def #{name} + ActiveRecord::Configuration.#{name} + end + CODE + end + + ClassMethods.class_eval <<-CODE, __FILE__, __LINE__ + def #{name}=(val) + ActiveRecord::Configuration.#{name} = val + end + CODE + + send("#{name}=", default) unless default.nil? + end + end +end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 0df62b7c62..b3db41f1d3 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -4,67 +4,64 @@ module ActiveRecord module Core extend ActiveSupport::Concern + ## + # :singleton-method: + # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, + # 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+. + Configuration.define :logger + + ## + # :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' + # } + # } + Configuration.define :configurations, {} + + ## + # :singleton-method: + # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling + # dates and times from the database. This is set to :local by default. + Configuration.define :default_timezone, :local + + ## + # :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. + Configuration.define :schema_format, :ruby + + ## + # :singleton-method: + # Specify whether or not to use timestamps for migration versions + Configuration.define :timestamped_migrations, true + included do - ## - # :singleton-method: - # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, - # 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+. - cattr_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' - # } - # } - cattr_accessor :configurations, :instance_writer => false - self.configurations = {} - - ## - # :singleton-method: - # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling - # dates and times from the database. This is set to :local by default. - cattr_accessor :default_timezone, :instance_writer => false - self.default_timezone = :local - - ## - # :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. - cattr_accessor :schema_format , :instance_writer => false - self.schema_format = :ruby - - ## - # :singleton-method: - # Specify whether or not to use timestamps for migration versions - cattr_accessor :timestamped_migrations , :instance_writer => false - self.timestamped_migrations = true ## # :singleton-method: diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 27267c9d38..b80d01db81 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -48,10 +48,7 @@ module ActiveRecord module Optimistic extend ActiveSupport::Concern - included do - cattr_accessor :lock_optimistically, :instance_writer => false - self.lock_optimistically = true - end + Configuration.define :lock_optimistically, true def locking_enabled? #:nodoc: self.class.locking_enabled? diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb index 9a8f7a93b6..e1d3db1aec 100644 --- a/activerecord/lib/active_record/model.rb +++ b/activerecord/lib/active_record/model.rb @@ -9,6 +9,8 @@ module ActiveRecord base.class_eval do include Tag + include Configuration + include ActiveRecord::Persistence extend ActiveModel::Naming extend QueryCache::ClassMethods @@ -43,7 +45,7 @@ module ActiveRecord include Core - self.connection_handler = ActiveRecord::Base.connection_handler + self.connection_handler = Base.connection_handler end end end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 5754806cdd..08f3451254 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -1,20 +1,20 @@ require 'active_support/concern' +require 'active_support/core_ext/class/attribute_accessors' module ActiveRecord module ModelSchema extend ActiveSupport::Concern - included do - ## - # :singleton-method: - # Accessor for the prefix type that will be prepended to every primary key column name. - # The options are :table_name and :table_name_with_underscore. If the first is specified, - # 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. - cattr_accessor :primary_key_prefix_type, :instance_writer => false - self.primary_key_prefix_type = nil + ## + # :singleton-method: + # Accessor for the prefix type that will be prepended to every primary key column name. + # The options are :table_name and :table_name_with_underscore. If the first is specified, + # 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. + Configuration.define :primary_key_prefix_type + included do ## # :singleton-method: # Accessor for the name of the prefix string to prepend to every table name. So if set diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index 0df9ffc0c5..375c207d20 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -18,6 +18,7 @@ module ActiveRecord def self.active_record_super; Base; end def self.base_class; self; end + include ActiveRecord::Configuration include ActiveRecord::AttributeMethods def self.column_names diff --git a/activerecord/test/cases/configuration_test.rb b/activerecord/test/cases/configuration_test.rb new file mode 100644 index 0000000000..872f1fc33b --- /dev/null +++ b/activerecord/test/cases/configuration_test.rb @@ -0,0 +1,26 @@ +require 'cases/helper' + +class ConfigurationTest < ActiveRecord::TestCase + def test_configuration + @klass = Class.new do + include ActiveRecord::Configuration + end + + ActiveRecord::Configuration.define :omg + + ActiveRecord::Configuration.omg = "omg" + + assert_equal "omg", @klass.new.omg + assert !@klass.new.respond_to?(:omg=) + assert_equal "omg", @klass.omg + + @klass.omg = "wtf" + + assert_equal "wtf", @klass.omg + assert_equal "wtf", @klass.new.omg + ensure + ActiveRecord::Configuration.send(:undef_method, :omg) + ActiveRecord::Configuration::ClassMethods.send(:undef_method, :omg) + ActiveRecord::Configuration::ClassMethods.send(:undef_method, :omg=) + end +end diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb index d092e748e8..ee32a71ca9 100644 --- a/activerecord/test/cases/inclusion_test.rb +++ b/activerecord/test/cases/inclusion_test.rb @@ -41,4 +41,13 @@ class InclusionUnitTest < ActiveRecord::TestCase 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 end