aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md2
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb4
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb3
-rw-r--r--activemodel/lib/active_model/configuration.rb134
-rw-r--r--activemodel/lib/active_model/mass_assignment_security.rb22
-rw-r--r--activemodel/lib/active_model/serializers/json.rb3
-rw-r--r--activemodel/lib/active_model/validations.rb5
-rw-r--r--activemodel/test/cases/configuration_test.rb154
-rw-r--r--activerecord/lib/active_record.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb5
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb7
-rw-r--r--activerecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/callbacks.rb51
-rw-r--r--activerecord/lib/active_record/configuration.rb36
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb184
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb79
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_handling.rb100
-rw-r--r--activerecord/lib/active_record/core.rb138
-rw-r--r--activerecord/lib/active_record/explain.rb8
-rw-r--r--activerecord/lib/active_record/inheritance.rb24
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb5
-rw-r--r--activerecord/lib/active_record/model.rb94
-rw-r--r--activerecord/lib/active_record/model_schema.rb30
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/lib/active_record/railtie.rb2
-rw-r--r--activerecord/lib/active_record/readonly_attributes.rb2
-rw-r--r--activerecord/lib/active_record/reflection.rb3
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb69
-rw-r--r--activerecord/lib/active_record/scoping/default.rb2
-rw-r--r--activerecord/lib/active_record/scoping/named.rb6
-rw-r--r--activerecord/lib/active_record/timestamp.rb2
-rw-r--r--activerecord/test/cases/adapter_test.rb6
-rw-r--r--activerecord/test/cases/adapters/mysql/connection_test.rb16
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb6
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb1
-rw-r--r--activerecord/test/cases/base_test.rb19
-rw-r--r--activerecord/test/cases/configuration_test.rb26
-rw-r--r--activerecord/test/cases/connection_adapters/abstract_adapter_test.rb2
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb2
-rw-r--r--activerecord/test/cases/inclusion_test.rb5
-rw-r--r--activerecord/test/cases/inheritance_test.rb1
-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/unconnected_test.rb6
-rw-r--r--activerecord/test/models/teapot.rb3
-rw-r--r--activerecord/test/schema/schema.rb1
-rw-r--r--activerecord/test/support/connection.rb6
-rw-r--r--activesupport/lib/active_support/base64.rb6
-rw-r--r--activesupport/lib/active_support/callbacks.rb14
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb2
-rw-r--r--activesupport/lib/active_support/message_verifier.rb4
-rw-r--r--activesupport/test/core_ext/base64_ext_test.rb6
-rw-r--r--activesupport/test/message_encryptor_test.rb2
-rw-r--r--railties/lib/rails/generators/actions.rb1
65 files changed, 834 insertions, 524 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 0c1228b7c6..c992f1388a 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 3.2.0 (unreleased) ##
+* Depends on rack ~> 1.4.0 *Santiago Pastorino*
+
* Add :gzip option to `caches_page`. The default option can be configured globally using `page_cache_compression` *Andrey Sitnik*
* The ShowExceptions middleware now accepts a exceptions application that is responsible to render an exception when the application fails. The application is invoked with a copy of the exception in `env["action_dispatch.exception"]` and with the PATH_INFO rewritten to the status code. *José Valim*
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index e369277e5a..dbf78a6d94 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
s.add_dependency('activemodel', version)
s.add_dependency('rack-cache', '~> 1.1')
s.add_dependency('builder', '~> 3.0.0')
- s.add_dependency('rack', '~> 1.3.5')
+ s.add_dependency('rack', '~> 1.4.0')
s.add_dependency('rack-test', '~> 0.6.1')
s.add_dependency('journey', '~> 1.0.0.rc1')
s.add_dependency('sprockets', '~> 2.1.2')
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 56335a22cb..594ba7a7b8 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -145,7 +145,7 @@ module ActionController
end
def encode_credentials(user_name, password)
- "Basic #{ActiveSupport::Base64.encode64s("#{user_name}:#{password}")}"
+ "Basic #{ActiveSupport::Base64.strict_encode64("#{user_name}:#{password}")}"
end
def authentication_request(controller, realm)
@@ -289,7 +289,7 @@ module ActionController
t = time.to_i
hashed = [t, secret_key]
digest = ::Digest::MD5.hexdigest(hashed.join(":"))
- ActiveSupport::Base64.encode64("#{t}:#{digest}").gsub("\n", '')
+ ActiveSupport::Base64.strict_encode64("#{t}:#{digest}")
end
# Might want a shorter timeout depending on whether the request
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index d0e2a6f39c..9fc308375f 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -32,6 +32,7 @@ module ActiveModel
autoload :AttributeMethods
autoload :BlockValidator, 'active_model/validator'
autoload :Callbacks
+ autoload :Configuration
autoload :Conversion
autoload :Dirty
autoload :EachValidator, 'active_model/validator'
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index d7ec7e6ca5..71ab1501c8 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -61,7 +61,8 @@ module ActiveModel
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
included do
- class_attribute :attribute_method_matchers, :instance_writer => false
+ extend ActiveModel::Configuration
+ config_attribute :attribute_method_matchers
self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new]
end
diff --git a/activemodel/lib/active_model/configuration.rb b/activemodel/lib/active_model/configuration.rb
new file mode 100644
index 0000000000..1757c12ebf
--- /dev/null
+++ b/activemodel/lib/active_model/configuration.rb
@@ -0,0 +1,134 @@
+require 'active_support/concern'
+require 'active_support/core_ext/class/attribute'
+require 'active_support/core_ext/class/attribute_accessors'
+
+module ActiveModel
+ # This API is for Rails' internal use and is not currently considered 'public', so
+ # it may change in the future without warning.
+ #
+ # It creates configuration attributes that can be inherited from a module down
+ # to a class that includes the module. E.g.
+ #
+ # module MyModel
+ # extend ActiveModel::Configuration
+ # config_attribute :awesome
+ # self.awesome = true
+ # end
+ #
+ # class Post
+ # include MyModel
+ # end
+ #
+ # Post.awesome # => true
+ #
+ # Post.awesome = false
+ # Post.awesome # => false
+ # MyModel.awesome # => true
+ #
+ # We assume that the module will have a ClassMethods submodule containing methods
+ # to be transferred to the including class' singleton class.
+ #
+ # Config options can also be defined directly on a class:
+ #
+ # class Post
+ # extend ActiveModel::Configuration
+ # config_attribute :awesome
+ # end
+ #
+ # So this allows us to define a module that doesn't care about whether it is being
+ # included in a class or a module:
+ #
+ # module Awesomeness
+ # extend ActiveSupport::Concern
+ #
+ # included do
+ # extend ActiveModel::Configuration
+ # config_attribute :awesome
+ # self.awesome = true
+ # end
+ # end
+ #
+ # class Post
+ # include Awesomeness
+ # end
+ #
+ # module AwesomeModel
+ # include Awesomeness
+ # end
+ module Configuration #:nodoc:
+ def config_attribute(name, options = {})
+ klass = self.is_a?(Class) ? ClassAttribute : ModuleAttribute
+ klass.new(self, name, options).define
+ end
+
+ class Attribute
+ attr_reader :host, :name, :options
+
+ def initialize(host, name, options)
+ @host, @name, @options = host, name, options
+ end
+
+ def instance_writer?
+ options.fetch(:instance_writer, false)
+ end
+ end
+
+ class ClassAttribute < Attribute
+ def define
+ if options[:global]
+ host.cattr_accessor name, :instance_writer => instance_writer?
+ else
+ host.class_attribute name, :instance_writer => instance_writer?
+ end
+ end
+ end
+
+ class ModuleAttribute < Attribute
+ def class_methods
+ @class_methods ||= begin
+ if host.const_defined?(:ClassMethods, false)
+ host.const_get(:ClassMethods)
+ else
+ host.const_set(:ClassMethods, Module.new)
+ end
+ end
+ end
+
+ def define
+ host.singleton_class.class_eval <<-CODE, __FILE__, __LINE__
+ attr_accessor :#{name}
+ def #{name}?; !!#{name}; end
+ CODE
+
+ name, host = self.name, self.host
+
+ class_methods.class_eval do
+ define_method(name) { host.send(name) }
+ define_method("#{name}?") { !!send(name) }
+ end
+
+ host.class_eval <<-CODE
+ def #{name}; defined?(@#{name}) ? @#{name} : self.class.#{name}; end
+ def #{name}?; !!#{name}; end
+ CODE
+
+ if options[:global]
+ class_methods.class_eval do
+ define_method("#{name}=") { |val| host.send("#{name}=", val) }
+ end
+ else
+ class_methods.class_eval <<-CODE, __FILE__, __LINE__
+ def #{name}=(val)
+ singleton_class.class_eval do
+ remove_possible_method(:#{name})
+ define_method(:#{name}) { val }
+ end
+ end
+ CODE
+ end
+
+ host.send(:attr_writer, name) if instance_writer?
+ end
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb
index c895968f77..9b12d9d281 100644
--- a/activemodel/lib/active_model/mass_assignment_security.rb
+++ b/activemodel/lib/active_model/mass_assignment_security.rb
@@ -10,11 +10,13 @@ module ActiveModel
extend ActiveSupport::Concern
included do
- class_attribute :_accessible_attributes
- class_attribute :_protected_attributes
- class_attribute :_active_authorizer
+ extend ActiveModel::Configuration
- class_attribute :_mass_assignment_sanitizer
+ config_attribute :_accessible_attributes
+ config_attribute :_protected_attributes
+ config_attribute :_active_authorizer
+
+ config_attribute :_mass_assignment_sanitizer
self.mass_assignment_sanitizer = :logger
end
@@ -56,7 +58,7 @@ module ActiveModel
# You can specify your own sanitizer object eg. MySanitizer.new.
# See <tt>ActiveModel::MassAssignmentSecurity::LoggerSanitizer</tt> for example implementation.
#
- #
+ #
module ClassMethods
# Attributes named in this macro are protected from mass-assignment
# whenever attributes are sanitized before assignment. A role for the
@@ -70,13 +72,13 @@ module ActiveModel
#
# class Customer
# include ActiveModel::MassAssignmentSecurity
- #
+ #
# attr_accessor :name, :email, :logins_count
- #
+ #
# attr_protected :logins_count
# # Suppose that admin can not change email for customer
- # attr_protected :logins_count, :email, :as => :admin
- #
+ # attr_protected :logins_count, :email, :as => :admin
+ #
# def assign_attributes(values, options = {})
# sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
# send("#{k}=", v)
@@ -99,7 +101,7 @@ module ActiveModel
# customer.name # => "David"
# customer.email # => nil
# customer.logins_count # => nil
- #
+ #
# customer.email = "c@d.com"
# customer.email # => "c@d.com"
#
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index c845440120..63ab8e7edc 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -10,8 +10,9 @@ module ActiveModel
included do
extend ActiveModel::Naming
+ extend ActiveModel::Configuration
- class_attribute :include_root_in_json
+ config_attribute :include_root_in_json
self.include_root_in_json = true
end
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 8ed392abca..1779efd526 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -42,9 +42,9 @@ module ActiveModel
#
module Validations
extend ActiveSupport::Concern
- include ActiveSupport::Callbacks
included do
+ extend ActiveModel::Callbacks
extend ActiveModel::Translation
extend HelperMethods
@@ -53,7 +53,8 @@ module ActiveModel
attr_accessor :validation_context
define_callbacks :validate, :scope => :name
- class_attribute :_validators
+ extend ActiveModel::Configuration
+ config_attribute :_validators
self._validators = Hash.new { |h,k| h[k] = [] }
end
diff --git a/activemodel/test/cases/configuration_test.rb b/activemodel/test/cases/configuration_test.rb
new file mode 100644
index 0000000000..a172fa26a3
--- /dev/null
+++ b/activemodel/test/cases/configuration_test.rb
@@ -0,0 +1,154 @@
+require 'cases/helper'
+
+class ConfigurationOnModuleTest < ActiveModel::TestCase
+ def setup
+ @mod = mod = Module.new do
+ extend ActiveSupport::Concern
+ extend ActiveModel::Configuration
+
+ config_attribute :omg
+ self.omg = "default"
+
+ config_attribute :wtf, global: true
+ self.wtf = "default"
+
+ config_attribute :boolean
+
+ config_attribute :lol, instance_writer: true
+ end
+
+ @klass = Class.new do
+ include mod
+ end
+
+ @subklass = Class.new(@klass)
+ end
+
+ test "default" do
+ assert_equal "default", @mod.omg
+ assert_equal "default", @klass.omg
+ assert_equal "default", @klass.new.omg
+ end
+
+ test "setting" do
+ @mod.omg = "lol"
+ assert_equal "lol", @mod.omg
+ end
+
+ test "setting on class including the module" do
+ @klass.omg = "lol"
+ assert_equal "lol", @klass.omg
+ assert_equal "lol", @klass.new.omg
+ assert_equal "default", @mod.omg
+ end
+
+ test "setting on subclass of class including the module" do
+ @subklass.omg = "lol"
+ assert_equal "lol", @subklass.omg
+ assert_equal "default", @klass.omg
+ assert_equal "default", @mod.omg
+ end
+
+ test "setting on instance" do
+ assert !@klass.new.respond_to?(:omg=)
+
+ @klass.lol = "lol"
+ obj = @klass.new
+ assert_equal "lol", obj.lol
+ obj.lol = "omg"
+ assert_equal "omg", obj.lol
+ assert_equal "lol", @klass.lol
+ assert_equal "lol", @klass.new.lol
+ obj.lol = false
+ assert !obj.lol?
+ end
+
+ test "global attribute" do
+ assert_equal "default", @mod.wtf
+ assert_equal "default", @klass.wtf
+
+ @mod.wtf = "wtf"
+
+ assert_equal "wtf", @mod.wtf
+ assert_equal "wtf", @klass.wtf
+
+ @klass.wtf = "lol"
+
+ assert_equal "lol", @mod.wtf
+ assert_equal "lol", @klass.wtf
+ end
+
+ test "boolean" do
+ assert_equal false, @mod.boolean?
+ assert_equal false, @klass.new.boolean?
+ @mod.boolean = true
+ assert_equal true, @mod.boolean?
+ assert_equal true, @klass.new.boolean?
+ end
+end
+
+class ConfigurationOnClassTest < ActiveModel::TestCase
+ def setup
+ @klass = Class.new do
+ extend ActiveModel::Configuration
+
+ config_attribute :omg
+ self.omg = "default"
+
+ config_attribute :wtf, global: true
+ self.wtf = "default"
+
+ config_attribute :omg2, instance_writer: true
+ config_attribute :wtf2, instance_writer: true, global: true
+ end
+
+ @subklass = Class.new(@klass)
+ end
+
+ test "defaults" do
+ assert_equal "default", @klass.omg
+ assert_equal "default", @klass.wtf
+ assert_equal "default", @subklass.omg
+ assert_equal "default", @subklass.wtf
+ end
+
+ test "changing" do
+ @klass.omg = "lol"
+ assert_equal "lol", @klass.omg
+ assert_equal "lol", @subklass.omg
+ end
+
+ test "changing in subclass" do
+ @subklass.omg = "lol"
+ assert_equal "lol", @subklass.omg
+ assert_equal "default", @klass.omg
+ end
+
+ test "changing global" do
+ @klass.wtf = "wtf"
+ assert_equal "wtf", @klass.wtf
+ assert_equal "wtf", @subklass.wtf
+
+ @subklass.wtf = "lol"
+ assert_equal "lol", @klass.wtf
+ assert_equal "lol", @subklass.wtf
+ end
+
+ test "instance_writer" do
+ obj = @klass.new
+
+ @klass.omg2 = "omg"
+ @klass.wtf2 = "wtf"
+
+ assert_equal "omg", obj.omg2
+ assert_equal "wtf", obj.wtf2
+
+ obj.omg2 = "lol"
+ obj.wtf2 = "lol"
+
+ assert_equal "lol", obj.omg2
+ assert_equal "lol", obj.wtf2
+ assert_equal "omg", @klass.omg2
+ assert_equal "lol", @klass.wtf2
+ end
+end
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 4d143146d5..4f194cb6cf 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -57,9 +57,9 @@ module ActiveRecord
autoload :Base
autoload :Callbacks
- autoload :Configuration
autoload :Core
autoload :CounterCache
+ autoload :ConnectionHandling
autoload :DynamicMatchers
autoload :DynamicFinderMatch
autoload :DynamicScopeMatch
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 44b0956e4e..c5834e2fef 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -61,7 +61,7 @@ module ActiveRecord
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord"
end
- if active_record_super == Base
+ if [Base, Model].include?(active_record_super)
super
else
# If B < A and A defines its own attribute method, then we don't want to overwrite that.
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index f61e016f46..40e4a97e73 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -13,7 +13,7 @@ module ActiveRecord
raise "You cannot include Dirty after Timestamp"
end
- class_attribute :partial_updates
+ config_attribute :partial_updates
self.partial_updates = true
end
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 7d2d1db4b5..964c4123ef 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -5,7 +5,10 @@ module ActiveRecord
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
- Configuration.define :attribute_types_cached_by_default, ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
+ included do
+ config_attribute :attribute_types_cached_by_default, :global => true
+ self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
+ end
module ClassMethods
# +cache_attributes+ allows you to declare which converted attribute values should
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 2ffd91f796..0c8e4e4b9a 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -6,7 +6,7 @@ module ActiveRecord
included do
# Returns a hash of all the attributes that have been specified for serialization as
# keys and their class restriction as values.
- class_attribute :serialized_attributes
+ config_attribute :serialized_attributes
self.serialized_attributes = {}
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 5e5392441b..2f86e32f41 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,11 @@ module ActiveRecord
module TimeZoneConversion
extend ActiveSupport::Concern
- Configuration.define :time_zone_aware_attributes, false
-
included do
- class_attribute :skip_time_zone_conversion_for_attributes, :instance_writer => false
+ config_attribute :time_zone_aware_attributes, :global => true
+ self.time_zone_aware_attributes = false
+
+ config_attribute :skip_time_zone_conversion_for_attributes
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 6085df7d9f..d29cf82dad 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -328,9 +328,7 @@ module ActiveRecord #:nodoc:
# instances in the current object space.
class Base
include ActiveRecord::Model
- self.connection_handler = ConnectionAdapters::ConnectionHandler.new
end
end
-require 'active_record/connection_adapters/abstract/connection_specification'
ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Model::DeprecationProxy)
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index a175bf003c..8b2fc69b00 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -25,7 +25,7 @@ module ActiveRecord
# Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
# <tt>after_rollback</tt>.
#
- # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
+ # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
# is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
# are instantiated as well.
#
@@ -215,24 +215,48 @@ module ActiveRecord
# instead of quietly returning +false+.
#
# == Debugging callbacks
- #
- # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
+ #
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
# defines what part of the chain the callback runs in.
- #
- # To find all callbacks in the before_save callback chain:
- #
+ #
+ # To find all callbacks in the before_save callback chain:
+ #
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
- #
+ #
# Returns an array of callback objects that form the before_save chain.
- #
+ #
# To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
- #
+ #
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
- #
+ #
# Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
- #
+ #
module Callbacks
+ # We can't define callbacks directly on ActiveRecord::Model because
+ # it is a module. So we queue up the definitions and execute them
+ # when ActiveRecord::Model is included.
+ module Register #:nodoc:
+ def self.extended(base)
+ base.config_attribute :_callbacks_register
+ base._callbacks_register = []
+ end
+
+ def self.setup(base)
+ base._callbacks_register.each do |item|
+ base.send(*item)
+ end
+ end
+
+ def define_callbacks(*args)
+ self._callbacks_register << [:define_callbacks, *args]
+ end
+
+ def define_model_callbacks(*args)
+ self._callbacks_register << [:define_model_callbacks, *args]
+ end
+ end
+
extend ActiveSupport::Concern
CALLBACKS = [
@@ -242,8 +266,11 @@ module ActiveRecord
:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
]
+ module ClassMethods
+ include ActiveModel::Callbacks
+ end
+
included do
- extend ActiveModel::Callbacks
include ActiveModel::Validations::Callbacks
define_model_callbacks :initialize, :find, :touch, :only => :after
diff --git a/activerecord/lib/active_record/configuration.rb b/activerecord/lib/active_record/configuration.rb
deleted file mode 100644
index d58ed82258..0000000000
--- a/activerecord/lib/active_record/configuration.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-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/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 5749d45a18..ea738cb305 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -370,7 +370,7 @@ connection. For example: ActiveRecord::Base.connection.close
def retrieve_connection_pool(klass)
pool = @class_to_pool[klass.name]
return pool if pool
- return nil if ActiveRecord::Base == klass
+ return nil if ActiveRecord::Model == klass
retrieve_connection_pool klass.active_record_super
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
deleted file mode 100644
index 63e4020113..0000000000
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-require 'active_support/core_ext/module/delegation'
-
-module ActiveRecord
- module Core
- class ConnectionSpecification #:nodoc:
- attr_reader :config, :adapter_method
- def initialize (config, adapter_method)
- @config, @adapter_method = config, adapter_method
- end
-
- ##
- # Builds a ConnectionSpecification from user input
- class Resolver # :nodoc:
- attr_reader :config, :klass, :configurations
-
- def initialize(config, configurations)
- @config = config
- @configurations = configurations
- end
-
- def spec
- case config
- when nil
- raise AdapterNotSpecified unless defined?(Rails.env)
- resolve_string_connection Rails.env
- when Symbol, String
- resolve_string_connection config.to_s
- when Hash
- resolve_hash_connection config
- end
- end
-
- private
- def resolve_string_connection(spec) # :nodoc:
- hash = configurations.fetch(spec) do |k|
- connection_url_to_hash(k)
- end
-
- raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
-
- resolve_hash_connection hash
- end
-
- def resolve_hash_connection(spec) # :nodoc:
- spec = spec.symbolize_keys
-
- raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
-
- begin
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
- rescue LoadError => e
- raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
- end
-
- adapter_method = "#{spec[:adapter]}_connection"
-
- ConnectionSpecification.new(spec, adapter_method)
- end
-
- def connection_url_to_hash(url) # :nodoc:
- config = URI.parse url
- adapter = config.scheme
- adapter = "postgresql" if adapter == "postgres"
- spec = { :adapter => adapter,
- :username => config.user,
- :password => config.password,
- :port => config.port,
- :database => config.path.sub(%r{^/},""),
- :host => config.host }
- spec.reject!{ |_,value| !value }
- if config.query
- options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
- spec.merge!(options)
- end
- spec
- end
- end
- end
-
- # Returns the connection currently associated with the class. This can
- # also be used to "borrow" the connection to do database work that isn't
- # easily done without going straight to SQL.
- def connection
- self.class.connection
- end
-
- module ClassMethods
- # Establishes the connection to the database. Accepts a hash as input where
- # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
- # example for regular databases (MySQL, Postgresql, etc):
- #
- # ActiveRecord::Base.establish_connection(
- # :adapter => "mysql",
- # :host => "localhost",
- # :username => "myuser",
- # :password => "mypass",
- # :database => "somedatabase"
- # )
- #
- # Example for SQLite database:
- #
- # ActiveRecord::Base.establish_connection(
- # :adapter => "sqlite",
- # :database => "path/to/dbfile"
- # )
- #
- # Also accepts keys as strings (for parsing from YAML for example):
- #
- # ActiveRecord::Base.establish_connection(
- # "adapter" => "sqlite",
- # "database" => "path/to/dbfile"
- # )
- #
- # Or a URL:
- #
- # ActiveRecord::Base.establish_connection(
- # "postgres://myuser:mypass@localhost/somedatabase"
- # )
- #
- # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
- # may be returned on an error.
- def establish_connection(spec = ENV["DATABASE_URL"])
- resolver = ConnectionSpecification::Resolver.new spec, configurations
- spec = resolver.spec
-
- unless respond_to?(spec.adapter_method)
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
- end
-
- remove_connection
- connection_handler.establish_connection name, spec
- end
-
- # Returns the connection currently associated with the class. This can
- # also be used to "borrow" the connection to do database work unrelated
- # to any of the specific Active Records.
- def connection
- retrieve_connection
- end
-
- def connection_id
- Thread.current['ActiveRecord::Base.connection_id']
- end
-
- def connection_id=(connection_id)
- Thread.current['ActiveRecord::Base.connection_id'] = connection_id
- end
-
- # Returns the configuration of the associated connection as a hash:
- #
- # ActiveRecord::Base.connection_config
- # # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
- #
- # Please use only for reading.
- def connection_config
- connection_pool.spec.config
- end
-
- def connection_pool
- connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
- end
-
- def retrieve_connection
- connection_handler.retrieve_connection(self)
- end
-
- # Returns true if Active Record is connected.
- def connected?
- connection_handler.connected?(self)
- end
-
- def remove_connection(klass = self)
- connection_handler.remove_connection(klass)
- end
-
- def clear_active_connections!
- connection_handler.clear_active_connections!
- end
-
- delegate :clear_reloadable_connections!,
- :clear_all_connections!,:verify_active_connections!, :to => :connection_handler
- end
- end
-end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 5a2493f69d..edea414db7 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -11,6 +11,7 @@ module ActiveRecord
extend ActiveSupport::Autoload
autoload :Column
+ autoload :ConnectionSpecification
autoload_under 'abstract' do
autoload :IndexDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
@@ -26,7 +27,6 @@ module ActiveRecord
autoload :ConnectionPool
autoload :ConnectionHandler, 'active_record/connection_adapters/abstract/connection_pool'
autoload :ConnectionManagement, 'active_record/connection_adapters/abstract/connection_pool'
- autoload :ConnectionSpecification
autoload :QueryCache
end
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
new file mode 100644
index 0000000000..3e67c3a2b7
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -0,0 +1,79 @@
+module ActiveRecord
+ module ConnectionAdapters
+ class ConnectionSpecification #:nodoc:
+ attr_reader :config, :adapter_method
+
+ def initialize (config, adapter_method)
+ @config, @adapter_method = config, adapter_method
+ end
+
+ ##
+ # Builds a ConnectionSpecification from user input
+ class Resolver # :nodoc:
+ attr_reader :config, :klass, :configurations
+
+ def initialize(config, configurations)
+ @config = config
+ @configurations = configurations
+ end
+
+ def spec
+ case config
+ when nil
+ raise AdapterNotSpecified unless defined?(Rails.env)
+ resolve_string_connection Rails.env
+ when Symbol, String
+ resolve_string_connection config.to_s
+ when Hash
+ resolve_hash_connection config
+ end
+ end
+
+ private
+ def resolve_string_connection(spec) # :nodoc:
+ hash = configurations.fetch(spec) do |k|
+ connection_url_to_hash(k)
+ end
+
+ raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
+
+ resolve_hash_connection hash
+ end
+
+ def resolve_hash_connection(spec) # :nodoc:
+ spec = spec.symbolize_keys
+
+ raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
+
+ begin
+ require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
+ rescue LoadError => e
+ raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
+ end
+
+ adapter_method = "#{spec[:adapter]}_connection"
+
+ ConnectionSpecification.new(spec, adapter_method)
+ end
+
+ def connection_url_to_hash(url) # :nodoc:
+ config = URI.parse url
+ adapter = config.scheme
+ adapter = "postgresql" if adapter == "postgres"
+ spec = { :adapter => adapter,
+ :username => config.user,
+ :password => config.password,
+ :port => config.port,
+ :database => config.path.sub(%r{^/},""),
+ :host => config.host }
+ spec.reject!{ |_,value| !value }
+ if config.query
+ options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
+ spec.merge!(options)
+ end
+ spec
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index e51796871a..6086c32dbe 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -4,7 +4,7 @@ gem 'mysql2', '~> 0.3.10'
require 'mysql2'
module ActiveRecord
- module Core::ClassMethods
+ module ConnectionHandling
# Establishes a connection to the database that's used by all Active Record objects.
def mysql2_connection(config)
config[:username] = 'root' if config[:username].nil?
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 901d8422f2..e432c5af32 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -18,7 +18,7 @@ class Mysql
end
module ActiveRecord
- module Core::ClassMethods
+ module ConnectionHandling
# Establishes a connection to the database that's used by all Active Record objects.
def mysql_connection(config) # :nodoc:
config = config.symbolize_keys
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 74a9be99bd..d2361b5378 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -7,7 +7,7 @@ gem 'pg', '~> 0.11'
require 'pg'
module ActiveRecord
- module Core::ClassMethods
+ module ConnectionHandling
# Establishes a connection to the database that's used by all Active Record objects
def postgresql_connection(config) # :nodoc:
config = config.symbolize_keys
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index ac3fb72b6e..ee5d10859c 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -4,7 +4,7 @@ gem 'sqlite3', '~> 1.3.5'
require 'sqlite3'
module ActiveRecord
- module Core::ClassMethods
+ module ConnectionHandling
# sqlite3 adapter reuses sqlite_connection.
def sqlite3_connection(config) # :nodoc:
# Require database.
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
new file mode 100644
index 0000000000..e9cd3d5e57
--- /dev/null
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -0,0 +1,100 @@
+require 'active_support/core_ext/module/delegation'
+
+module ActiveRecord
+ module ConnectionHandling
+ # Establishes the connection to the database. Accepts a hash as input where
+ # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
+ # example for regular databases (MySQL, Postgresql, etc):
+ #
+ # ActiveRecord::Base.establish_connection(
+ # :adapter => "mysql",
+ # :host => "localhost",
+ # :username => "myuser",
+ # :password => "mypass",
+ # :database => "somedatabase"
+ # )
+ #
+ # Example for SQLite database:
+ #
+ # ActiveRecord::Base.establish_connection(
+ # :adapter => "sqlite",
+ # :database => "path/to/dbfile"
+ # )
+ #
+ # Also accepts keys as strings (for parsing from YAML for example):
+ #
+ # ActiveRecord::Base.establish_connection(
+ # "adapter" => "sqlite",
+ # "database" => "path/to/dbfile"
+ # )
+ #
+ # Or a URL:
+ #
+ # ActiveRecord::Base.establish_connection(
+ # "postgres://myuser:mypass@localhost/somedatabase"
+ # )
+ #
+ # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
+ # may be returned on an error.
+ def establish_connection(spec = ENV["DATABASE_URL"])
+ resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new spec, configurations
+ spec = resolver.spec
+
+ unless respond_to?(spec.adapter_method)
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
+ end
+
+ remove_connection
+ connection_handler.establish_connection name, spec
+ end
+
+ # Returns the connection currently associated with the class. This can
+ # also be used to "borrow" the connection to do database work unrelated
+ # to any of the specific Active Records.
+ def connection
+ retrieve_connection
+ end
+
+ def connection_id
+ Thread.current['ActiveRecord::Base.connection_id']
+ end
+
+ def connection_id=(connection_id)
+ Thread.current['ActiveRecord::Base.connection_id'] = connection_id
+ end
+
+ # Returns the configuration of the associated connection as a hash:
+ #
+ # ActiveRecord::Base.connection_config
+ # # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
+ #
+ # Please use only for reading.
+ def connection_config
+ connection_pool.spec.config
+ end
+
+ def connection_pool
+ connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
+ end
+
+ def retrieve_connection
+ connection_handler.retrieve_connection(self)
+ end
+
+ # Returns true if Active Record is connected.
+ def connected?
+ connection_handler.connected?(self)
+ end
+
+ def remove_connection(klass = self)
+ connection_handler.remove_connection(klass)
+ end
+
+ def clear_active_connections!
+ connection_handler.clear_active_connections!
+ end
+
+ delegate :clear_reloadable_connections!,
+ :clear_all_connections!,:verify_active_connections!, :to => :connection_handler
+ end
+end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 4f118e46a9..980f8fe50f 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -4,70 +4,73 @@ 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:
- # The connection handler
- class_attribute :connection_handler, :instance_writer => false
+ # 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+.
+ config_attribute :logger, :global => true
+
+ ##
+ # :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'
+ # }
+ # }
+ config_attribute :configurations, :global => true
+ 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.
+ config_attribute :default_timezone, :global => true
+ self.default_timezone = :local
- initialize_generated_modules unless self == Base
+ ##
+ # :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.
+ config_attribute :schema_format, :global => true
+ self.schema_format = :ruby
+
+ ##
+ # :singleton-method:
+ # Specify whether or not to use timestamps for migration versions
+ config_attribute :timestamped_migrations, :global => true
+ self.timestamped_migrations = true
+
+ ##
+ # :singleton-method:
+ # The connection handler
+ config_attribute :connection_handler
+ self.connection_handler = ConnectionAdapters::ConnectionHandler.new
end
module ClassMethods
@@ -114,13 +117,7 @@ module ActiveRecord
end
def arel_engine
- @arel_engine ||= begin
- if self == ActiveRecord::Base
- ActiveRecord::Base
- else
- connection_handler.connection_pools[name] ? self : active_record_super.arel_engine
- end
- end
+ @arel_engine ||= connection_handler.connection_pools[name] ? self : active_record_super.arel_engine
end
private
@@ -299,6 +296,13 @@ module ActiveRecord
@readonly = true
end
+ # Returns the connection currently associated with the class. This can
+ # also be used to "borrow" the connection to do database work that isn't
+ # easily done without going straight to SQL.
+ def connection
+ self.class.connection
+ end
+
# Returns the contents of the record as a nicely formatted string.
def inspect
inspection = if @attributes
diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb
index b5a67afd88..e502d7e52b 100644
--- a/activerecord/lib/active_record/explain.rb
+++ b/activerecord/lib/active_record/explain.rb
@@ -2,9 +2,11 @@ require 'active_support/core_ext/class/attribute'
module ActiveRecord
module Explain
- # If a query takes longer than these many seconds we log its query plan
- # automatically. nil disables this feature.
- Configuration.define :auto_explain_threshold_in_seconds
+ def self.extended(base)
+ # If a query takes longer than these many seconds we log its query plan
+ # automatically. nil disables this feature.
+ base.config_attribute :auto_explain_threshold_in_seconds, :global => true
+ 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/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index ec57151d40..eaa7deac5a 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -6,7 +6,7 @@ module ActiveRecord
included do
# Determine whether to store the full constant name including namespace when using STI
- class_attribute :store_full_sti_class
+ config_attribute :store_full_sti_class
self.store_full_sti_class = true
end
@@ -17,8 +17,10 @@ module ActiveRecord
if sup.abstract_class?
sup.descends_from_active_record?
+ elsif self == Base
+ false
else
- sup == Base || !columns_hash.include?(inheritance_column)
+ [Base, Model].include?(sup) || !columns_hash.include?(inheritance_column)
end
end
@@ -81,18 +83,12 @@ module ActiveRecord
instance
end
- # If this class includes ActiveRecord::Model then it won't have a
- # superclass. So this provides a way to get to the 'root' (ActiveRecord::Base),
- # through inheritance hierarchy, ending in Base, whether or not that is
- # actually an ancestor of the class.
+ # For internal use.
#
- # Mainly 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:
- if self == Base || superclass && superclass < Model::Tag
- superclass
- else
- Base
- end
+ superclass < Model ? superclass : Model
end
protected
@@ -100,12 +96,12 @@ module ActiveRecord
# Returns the class descending directly from ActiveRecord::Base or an
# abstract class, if any, in the inheritance hierarchy.
def class_of_active_record_descendant(klass)
- unless klass < Model::Tag
+ unless klass < Model
raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
end
sup = klass.active_record_super
- if klass == Base || sup == Base || sup.abstract_class?
+ if [Base, Model].include?(klass) || [Base, Model].include?(sup) || sup.abstract_class?
klass
else
class_of_active_record_descendant(sup)
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index b80d01db81..e643c0d437 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -48,7 +48,10 @@ module ActiveRecord
module Optimistic
extend ActiveSupport::Concern
- Configuration.define :lock_optimistically, true
+ included do
+ config_attribute :lock_optimistically, :global => true
+ self.lock_optimistically = true
+ end
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 f87be257db..86de5ab2fa 100644
--- a/activerecord/lib/active_record/model.rb
+++ b/activerecord/lib/active_record/model.rb
@@ -9,54 +9,74 @@ module ActiveRecord
# end
#
module Model
- # So we can recognise an AR class even while self.included is being
- # executed. (At that time, klass < Model == false.)
- module Tag #:nodoc:
+ module ClassMethods #:nodoc:
+ include ActiveSupport::Callbacks::ClassMethods
+ include ActiveModel::Naming
+ include QueryCache::ClassMethods
+ include ActiveSupport::Benchmarkable
+ include ActiveSupport::DescendantsTracker
+
+ include Querying
+ include Translation
+ include DynamicMatchers
+ include CounterCache
+ include Explain
+ include ConnectionHandling
end
def self.included(base)
- return if base < Tag
+ return if base.singleton_class < ClassMethods
base.class_eval do
- include Tag
+ extend ClassMethods
+ Callbacks::Register.setup(self)
+ initialize_generated_modules unless self == Base
+ end
+ end
- include Configuration
+ extend ActiveModel::Configuration
+ extend ActiveModel::Callbacks
+ extend ActiveModel::MassAssignmentSecurity::ClassMethods
+ extend ActiveModel::AttributeMethods::ClassMethods
+ extend Callbacks::Register
+ extend Explain
+ extend ConnectionHandling
- include ActiveRecord::Persistence
- extend ActiveModel::Naming
- extend QueryCache::ClassMethods
- extend ActiveSupport::Benchmarkable
- extend ActiveSupport::DescendantsTracker
+ def self.extend(*modules)
+ ClassMethods.send(:include, *modules)
+ end
- extend Querying
- include ReadonlyAttributes
- include ModelSchema
- extend Translation
- include Inheritance
- include Scoping
- extend DynamicMatchers
- include Sanitization
- include Integration
- include AttributeAssignment
- include ActiveModel::Conversion
- include Validations
- extend CounterCache
- include Locking::Optimistic, Locking::Pessimistic
- include AttributeMethods
- include Callbacks, ActiveModel::Observing, Timestamp
- include Associations
- include IdentityMap
- include ActiveModel::SecurePassword
- extend Explain
+ include Persistence
+ include ReadonlyAttributes
+ include ModelSchema
+ include Inheritance
+ include Scoping
+ include Sanitization
+ include Integration
+ include AttributeAssignment
+ include ActiveModel::Conversion
+ include Validations
+ include Locking::Optimistic, Locking::Pessimistic
+ include AttributeMethods
+ include Callbacks, ActiveModel::Observing, Timestamp
+ include Associations
+ include IdentityMap
+ include ActiveModel::SecurePassword
+ include AutosaveAssociation, NestedAttributes
+ include Aggregations, Transactions, Reflection, Serialization, Store
+ include Core
- # AutosaveAssociation needs to be included before Transactions, because we want
- # #save_with_autosave_associations to be wrapped inside a transaction.
- include AutosaveAssociation, NestedAttributes
- include Aggregations, Transactions, Reflection, Serialization, Store
+ class << self
+ def arel_engine
+ self
+ end
- include Core
+ def abstract_class?
+ false
+ end
- self.connection_handler = Base.connection_handler
+ def inheritance_column
+ 'type'
end
end
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index adf85c6436..c1a8583119 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -5,18 +5,18 @@ module ActiveRecord
module ModelSchema
extend ActiveSupport::Concern
- ##
- # :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 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.
+ config_attribute :primary_key_prefix_type, :global => true
+
+ ##
+ # :singleton-method:
# Accessor for the name of the prefix string to prepend to every table name. So if set
# to "basecamp_", all table names will be named like "basecamp_projects", "basecamp_people",
# etc. This is a convenient way of creating a namespace for tables in a shared database.
@@ -25,14 +25,14 @@ 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.
- class_attribute :table_name_prefix, :instance_writer => false
+ config_attribute :table_name_prefix
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.
- class_attribute :table_name_suffix, :instance_writer => false
+ config_attribute :table_name_suffix
self.table_name_suffix = ""
##
@@ -40,7 +40,7 @@ module ActiveRecord
# 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.
- class_attribute :pluralize_table_names, :instance_writer => false
+ config_attribute :pluralize_table_names
self.pluralize_table_names = true
end
@@ -143,11 +143,7 @@ module ActiveRecord
# The name of the column containing the object's class when Single Table Inheritance is used
def inheritance_column
- if self == Base
- 'type'
- else
- (@inheritance_column ||= nil) || active_record_super.inheritance_column
- end
+ (@inheritance_column ||= nil) || active_record_super.inheritance_column
end
# Sets the value of inheritance_column
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index d2065d701f..a8ee43b598 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -12,7 +12,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :nested_attributes_options, :instance_writer => false
+ config_attribute :nested_attributes_options
self.nested_attributes_options = {}
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 08cf9fb504..165d0750dd 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -108,7 +108,7 @@ module ActiveRecord
config.after_initialize do
ActiveSupport.on_load(:active_record) do
- instantiate_observers
+ ActiveRecord::Base.instantiate_observers
ActionDispatch::Reloader.to_prepare do
ActiveRecord::Base.instantiate_observers
diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb
index bf37ab5f14..836b15e2ce 100644
--- a/activerecord/lib/active_record/readonly_attributes.rb
+++ b/activerecord/lib/active_record/readonly_attributes.rb
@@ -6,7 +6,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :_attr_readonly, :instance_writer => false
+ config_attribute :_attr_readonly
self._attr_readonly = []
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 794a0526fb..60b73e9fe5 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -7,7 +7,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :reflections
+ extend ActiveModel::Configuration
+ config_attribute :reflections
self.reflections = {}
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index eee198e760..88081edae2 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -15,44 +15,49 @@ module ActiveRecord
table = Arel::Table.new(table_name, engine)
end
- attribute = table[column.to_sym]
-
- case value
- when ActiveRecord::Relation
- value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty?
- attribute.in(value.arel.ast)
- when Array, ActiveRecord::Associations::CollectionProxy
- values = value.to_a.map {|x| x.is_a?(ActiveRecord::Model) ? x.id : x}
- ranges, values = values.partition {|v| v.is_a?(Range) || v.is_a?(Arel::Relation)}
-
- array_predicates = ranges.map {|range| attribute.in(range)}
+ build(table[column.to_sym], value)
+ end
+ end
+ predicates.flatten
+ end
- if values.include?(nil)
- values = values.compact
- if values.empty?
- array_predicates << attribute.eq(nil)
- else
- array_predicates << attribute.in(values.compact).or(attribute.eq(nil))
- end
+ private
+ def self.build(attribute, value)
+ case value
+ when ActiveRecord::Relation
+ value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty?
+ attribute.in(value.arel.ast)
+ when Array, ActiveRecord::Associations::CollectionProxy
+ values = value.to_a.map {|x| x.is_a?(ActiveRecord::Model) ? x.id : x}
+ ranges, values = values.partition {|v| v.is_a?(Range) || v.is_a?(Arel::Relation)}
+
+ array_predicates = ranges.map {|range| attribute.in(range)}
+
+ if values.include?(nil)
+ values = values.compact
+ case values.length
+ when 0
+ array_predicates << attribute.eq(nil)
+ when 1
+ array_predicates << attribute.eq(values.first).or(attribute.eq(nil))
else
- array_predicates << attribute.in(values)
+ array_predicates << attribute.in(values).or(attribute.eq(nil))
end
-
- array_predicates.inject {|composite, predicate| composite.or(predicate)}
- when Range, Arel::Relation
- attribute.in(value)
- when ActiveRecord::Model
- attribute.eq(value.id)
- when Class
- # FIXME: I think we need to deprecate this behavior
- attribute.eq(value.name)
else
- attribute.eq(value)
+ array_predicates << attribute.in(values)
end
+
+ array_predicates.inject {|composite, predicate| composite.or(predicate)}
+ when Range, Arel::Relation
+ attribute.in(value)
+ when ActiveRecord::Model
+ attribute.eq(value.id)
+ when Class
+ # FIXME: I think we need to deprecate this behavior
+ attribute.eq(value.name)
+ else
+ attribute.eq(value)
end
end
-
- predicates.flatten
- end
end
end
diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb
index 6b5070808a..5f05d146f2 100644
--- a/activerecord/lib/active_record/scoping/default.rb
+++ b/activerecord/lib/active_record/scoping/default.rb
@@ -7,7 +7,7 @@ module ActiveRecord
included do
# Stores the default scope for the class
- class_attribute :default_scopes, :instance_writer => false
+ config_attribute :default_scopes
self.default_scopes = []
end
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 17122740da..0edc3f1dcc 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -118,16 +118,16 @@ module ActiveRecord
# when they are used. For example, the following would be incorrect:
#
# class Post < ActiveRecord::Base
- # scope :recent, where('published_at >= ?', Time.now - 1.week)
+ # scope :recent, where('published_at >= ?', Time.current - 1.week)
# end
#
- # The example above would be 'frozen' to the <tt>Time.now</tt> value when the <tt>Post</tt>
+ # The example above would be 'frozen' to the <tt>Time.current</tt> value when the <tt>Post</tt>
# class was defined, and so the resultant SQL query would always be the same. The correct
# way to do this would be via a lambda, which will re-evaluate the scope each time
# it is called:
#
# class Post < ActiveRecord::Base
- # scope :recent, lambda { where('published_at >= ?', Time.now - 1.week) }
+ # scope :recent, lambda { where('published_at >= ?', Time.current - 1.week) }
# end
#
# Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index 0c760e9850..c717fdea47 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -33,7 +33,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :record_timestamps
+ config_attribute :record_timestamps, :instance_writer => true
self.record_timestamps = true
end
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 56c359650e..852fc0e26e 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::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
+ ActiveRecord::Model.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
config = ARTest.connection_config
- ActiveRecord::Base.connection.execute(
+ ActiveRecord::Model.connection.execute(
"SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
"FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
)
end
ensure
- ActiveRecord::Base.establish_connection 'arunit'
+ ActiveRecord::Model.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 2a89430da9..fa2ba8d592 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::Base.connection
+ @connection = ActiveRecord::Model.connection
end
def test_mysql_reconnect_attribute_after_connection_with_reconnect_true
run_without_connection do |orig_connection|
- ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true}))
- assert ActiveRecord::Base.connection.raw_connection.reconnect
+ ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => true}))
+ assert ActiveRecord::Model.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::Base.establish_connection(orig_connection.merge({:reconnect => false}))
- assert !ActiveRecord::Base.connection.raw_connection.reconnect
+ ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => false}))
+ assert !ActiveRecord::Model.connection.raw_connection.reconnect
end
end
@@ -114,7 +114,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::Base.connection.select_rows('CALL ten();')
+ rows = ActiveRecord::Model.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
@@ -123,11 +123,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Base.remove_connection
+ original_connection = ActiveRecord::Model.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Base.establish_connection(original_connection)
+ ActiveRecord::Model.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index 26091c713b..8e2b9ca9a5 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::Base.connection
+ @connection = ActiveRecord::Model.connection
end
def test_no_automatic_reconnection_after_timeout
@@ -32,11 +32,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Base.remove_connection
+ original_connection = ActiveRecord::Model.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Base.establish_connection(original_connection)
+ ActiveRecord::Model.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index 375c207d20..0df9ffc0c5 100644
--- a/activerecord/test/cases/attribute_methods/read_test.rb
+++ b/activerecord/test/cases/attribute_methods/read_test.rb
@@ -18,7 +18,6 @@ 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/base_test.rb b/activerecord/test/cases/base_test.rb
index c465e9b556..80a660717e 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -23,6 +23,7 @@ require 'models/edge'
require 'models/joke'
require 'models/bulb'
require 'models/bird'
+require 'models/teapot'
require 'rexml/document'
require 'active_support/core_ext/exception'
require 'bcrypt'
@@ -1634,10 +1635,7 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_descends_from_active_record
- # Tries to call Object.abstract_class?
- assert_raise(NoMethodError) do
- ActiveRecord::Base.descends_from_active_record?
- end
+ assert !ActiveRecord::Base.descends_from_active_record?
# Abstract subclass of AR::Base.
assert LoosePerson.descends_from_active_record?
@@ -1660,6 +1658,10 @@ 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
@@ -1893,4 +1895,13 @@ class BasicsTest < ActiveRecord::TestCase
Bird.stubs(:scoped).returns(mock(:uniq => scope))
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
end
diff --git a/activerecord/test/cases/configuration_test.rb b/activerecord/test/cases/configuration_test.rb
deleted file mode 100644
index 872f1fc33b..0000000000
--- a/activerecord/test/cases/configuration_test.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-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/connection_adapters/abstract_adapter_test.rb b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
index 7af9079b48..7dc6e8afcb 100644
--- a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
+++ b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
@@ -35,7 +35,7 @@ module ActiveRecord
end
def test_close
- pool = ConnectionPool.new(Base::ConnectionSpecification.new({}, nil))
+ pool = ConnectionPool.new(ConnectionSpecification.new({}, nil))
pool.connections << adapter
adapter.pool = pool
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index 5f9a742285..e6cb1b9521 100644
--- a/activerecord/test/cases/connection_specification/resolver_test.rb
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -1,7 +1,7 @@
require "cases/helper"
module ActiveRecord
- module Core
+ module ConnectionAdapters
class ConnectionSpecification
class ResolverTest < ActiveRecord::TestCase
def resolve(spec)
diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb
index f2c442c2e1..8726ba5e51 100644
--- a/activerecord/test/cases/inclusion_test.rb
+++ b/activerecord/test/cases/inclusion_test.rb
@@ -56,10 +56,13 @@ class InclusionUnitTest < ActiveRecord::TestCase
def test_establish_connection
assert @klass.respond_to?(:establish_connection)
+ assert ActiveRecord::Model.respond_to?(:establish_connection)
end
def test_adapter_connection
- assert @klass.respond_to?("#{ActiveRecord::Base.connection_config[: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
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index fab858e09c..02df464469 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -65,7 +65,6 @@ class InheritanceTest < ActiveRecord::TestCase
end
def test_company_descends_from_active_record
- assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? }
assert AbstractCompany.descends_from_active_record?, 'AbstractCompany should descend from ActiveRecord::Base'
assert Company.descends_from_active_record?, 'Company should descend from ActiveRecord::Base'
assert !Class.new(Company).descends_from_active_record?, 'Company subclass should not descend from ActiveRecord::Base'
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 296621c0d1..fba3006ebe 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::Base.remove_connection
+ @connection = ActiveRecord::Model.remove_connection
end
def teardown
- ActiveRecord::Base.clear_all_connections!
- ActiveRecord::Base.establish_connection(@connection)
+ ActiveRecord::Model.clear_all_connections!
+ ActiveRecord::Model.establish_connection(@connection)
@per_test_teardown.each {|td| td.call }
end
def checkout_connections
- ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :wait_timeout => 0.3}))
+ ActiveRecord::Model.establish_connection(@connection.merge({:pool => 2, :wait_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::Base.establish_connection(@connection.merge({:pool => pool_size, :wait_timeout => 0.5}))
+ ActiveRecord::Model.establish_connection(@connection.merge({:pool => pool_size, :wait_timeout => 0.5}))
@connection_count = 0
@timed_out = 0
threads.times do
Thread.new do
begin
- conn = ActiveRecord::Base.connection_pool.checkout
+ conn = ActiveRecord::Model.connection_pool.checkout
sleep 0.1
- ActiveRecord::Base.connection_pool.checkin conn
+ ActiveRecord::Model.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::Base.connection_pool.connections.size
+ assert_equal 1, ActiveRecord::Model.connection_pool.connections.size
end
private
def add_record(name)
- ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
+ ActiveRecord::Model.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 0669707baf..b4d1a631fa 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::Base.remove_connection
+ connection = ActiveRecord::Model.remove_connection
model = Class.new(ActiveRecord::Base)
model.primary_key = 'foo'
assert_equal 'foo', model.primary_key
- ActiveRecord::Base.establish_connection(connection)
+ ActiveRecord::Model.establish_connection(connection)
assert_equal 'foo', model.primary_key
end
diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb
index e82ca3f93d..5a69054445 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::Base.connection
- @specification = ActiveRecord::Base.remove_connection
+ @underlying = ActiveRecord::Model.connection
+ @specification = ActiveRecord::Model.remove_connection
end
def teardown
@underlying = nil
- ActiveRecord::Base.establish_connection(@specification)
+ ActiveRecord::Model.establish_connection(@specification)
load_schema if in_memory_db?
end
diff --git a/activerecord/test/models/teapot.rb b/activerecord/test/models/teapot.rb
index ff18b6a96d..b035b18c1b 100644
--- a/activerecord/test/models/teapot.rb
+++ b/activerecord/test/models/teapot.rb
@@ -12,6 +12,9 @@ class Teapot
include ActiveRecord::Model
end
+class OtherTeapot < Teapot
+end
+
class OMFGIMATEAPOT
def aaahhh
"mmm"
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 8706732230..b06175cd3f 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -598,6 +598,7 @@ ActiveRecord::Schema.define do
create_table :teapots, :force => true do |t|
t.string :name
+ t.string :type
t.timestamps
end
diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb
index 56369da346..60fea46fd3 100644
--- a/activerecord/test/support/connection.rb
+++ b/activerecord/test/support/connection.rb
@@ -12,9 +12,9 @@ module ARTest
def self.connect
puts "Using #{connection_name} with Identity Map #{ActiveRecord::IdentityMap.enabled? ? 'on' : 'off'}"
- ActiveRecord::Base.logger = ActiveSupport::Logger.new("debug.log")
- ActiveRecord::Base.configurations = connection_config
- ActiveRecord::Base.establish_connection 'arunit'
+ ActiveRecord::Model.logger = ActiveSupport::Logger.new("debug.log")
+ ActiveRecord::Model.configurations = connection_config
+ ActiveRecord::Model.establish_connection 'arunit'
Course.establish_connection 'arunit2'
end
end
diff --git a/activesupport/lib/active_support/base64.rb b/activesupport/lib/active_support/base64.rb
index b43d2ce9a3..41a1a3469d 100644
--- a/activesupport/lib/active_support/base64.rb
+++ b/activesupport/lib/active_support/base64.rb
@@ -3,12 +3,16 @@ require 'base64'
module ActiveSupport
Base64 = ::Base64
+ # *DEPRECATED*: Use +Base64.strict_encode64+ instead.
+ #
# Encodes the value as base64 without the newline breaks. This makes the base64 encoding readily usable as URL parameters
# or memcache keys without further processing.
#
# ActiveSupport::Base64.encode64s("Original unencoded string")
# # => "T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw=="
def Base64.encode64s(value)
- encode64(value).gsub(/\n/, '')
+ ActiveSupport::Deprecation.warn "encode64s " \
+ "is deprecated. Use Base64.strict_encode64 instead", caller
+ strict_encode64(value)
end
end
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 2ebafa28dd..0495741c15 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -378,9 +378,6 @@ module ActiveSupport
module ClassMethods
# Generate the internal runner method called by +run_callbacks+.
def __define_runner(symbol) #:nodoc:
- name = __callback_runner_name(nil, symbol)
- undef_method(name) if method_defined?(name)
-
runner_method = "_run_#{symbol}_callbacks"
unless private_method_defined?(runner_method)
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
@@ -408,6 +405,11 @@ module ActiveSupport
object.send(name, &blk)
end
+ def __reset_runner(symbol)
+ name = __callback_runner_name(nil, symbol)
+ undef_method(name) if method_defined?(name)
+ end
+
def __callback_runner_name(key, kind)
"_run__#{self.name.hash.abs}__#{kind}__#{key.hash.abs}__callbacks"
end
@@ -423,7 +425,7 @@ module ActiveSupport
([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse.each do |target|
chain = target.send("_#{name}_callbacks")
yield target, chain.dup, type, filters, options
- target.__define_runner(name)
+ target.__reset_runner(name)
end
end
@@ -537,12 +539,12 @@ module ActiveSupport
chain = target.send("_#{symbol}_callbacks").dup
callbacks.each { |c| chain.delete(c) }
target.send("_#{symbol}_callbacks=", chain)
- target.__define_runner(symbol)
+ target.__reset_runner(symbol)
end
self.send("_#{symbol}_callbacks=", callbacks.dup.clear)
- __define_runner(symbol)
+ __reset_runner(symbol)
end
# Define sets of events in the object lifecycle that support callbacks.
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index 7d8a7fb687..476ba0b3d1 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -56,7 +56,7 @@ module ActiveSupport
encrypted_data = cipher.update(@serializer.dump(value))
encrypted_data << cipher.final
- [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--")
+ [encrypted_data, iv].map {|v| ActiveSupport::Base64.strict_encode64(v)}.join("--")
end
def _decrypt(encrypted_message)
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 30ac44f6fa..7cb5b1e82d 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -18,7 +18,7 @@ module ActiveSupport
# self.current_user = User.find(id)
# end
#
- # By default it uses Marshal to serialize the message. If you want to use another
+ # By default it uses Marshal to serialize the message. If you want to use another
# serialization method, you can set the serializer attribute to something that responds
# to dump and load, e.g.:
#
@@ -44,7 +44,7 @@ module ActiveSupport
end
def generate(value)
- data = ActiveSupport::Base64.encode64s(@serializer.dump(value))
+ data = ActiveSupport::Base64.strict_encode64(@serializer.dump(value))
"#{data}--#{generate_digest(data)}"
end
diff --git a/activesupport/test/core_ext/base64_ext_test.rb b/activesupport/test/core_ext/base64_ext_test.rb
index bd0e9f843d..544c990b3c 100644
--- a/activesupport/test/core_ext/base64_ext_test.rb
+++ b/activesupport/test/core_ext/base64_ext_test.rb
@@ -2,7 +2,9 @@ require 'abstract_unit'
class Base64Test < Test::Unit::TestCase
def test_no_newline_in_encoded_value
- assert_match(/\n/, ActiveSupport::Base64.encode64("oneverylongstringthatwouldnormallybesplitupbynewlinesbytheregularbase64"))
- assert_no_match(/\n/, ActiveSupport::Base64.encode64s("oneverylongstringthatwouldnormallybesplitupbynewlinesbytheregularbase64"))
+ ActiveSupport::Deprecation.silence do
+ assert_match(/\n/, ActiveSupport::Base64.encode64("oneverylongstringthatwouldnormallybesplitupbynewlinesbytheregularbase64"))
+ assert_no_match(/\n/, ActiveSupport::Base64.encode64s("oneverylongstringthatwouldnormallybesplitupbynewlinesbytheregularbase64"))
+ end
end
end
diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb
index db97c1b80b..11142a358f 100644
--- a/activesupport/test/message_encryptor_test.rb
+++ b/activesupport/test/message_encryptor_test.rb
@@ -78,7 +78,7 @@ class MessageEncryptorTest < ActiveSupport::TestCase
def munge(base64_string)
bits = ActiveSupport::Base64.decode64(base64_string)
bits.reverse!
- ActiveSupport::Base64.encode64s(bits)
+ ActiveSupport::Base64.strict_encode64(bits)
end
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index ca93f9ef9d..781d7bf47c 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -1,5 +1,6 @@
require 'open-uri'
require 'rbconfig'
+require 'active_support/core_ext/array/wrap'
module Rails
module Generators