aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/Rakefile15
-rw-r--r--activerecord/activerecord.gemspec12
-rw-r--r--activerecord/lib/active_record.rb13
-rw-r--r--activerecord/lib/active_record/association_preload.rb2
-rwxr-xr-xactiverecord/lib/active_record/associations.rb56
-rw-r--r--activerecord/lib/active_record/attribute_methods/primary_key.rb16
-rwxr-xr-xactiverecord/lib/active_record/base.rb200
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb11
-rwxr-xr-xactiverecord/lib/active_record/connection_adapters/abstract_adapter.rb1
-rw-r--r--activerecord/lib/active_record/errors.rb165
-rw-r--r--activerecord/lib/active_record/migration.rb4
-rw-r--r--activerecord/lib/active_record/named_scope.rb6
-rw-r--r--activerecord/lib/active_record/railtie.rb46
-rw-r--r--activerecord/lib/active_record/railties/databases.rake10
-rw-r--r--activerecord/lib/active_record/railties/log_subscriber.rb (renamed from activerecord/lib/active_record/railties/subscriber.rb)2
-rw-r--r--activerecord/lib/active_record/relation.rb4
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb28
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb8
-rw-r--r--activerecord/lib/active_record/version.rb5
-rw-r--r--activerecord/test/cases/ar_schema_test.rb10
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb32
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb20
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb4
-rwxr-xr-xactiverecord/test/cases/base_test.rb28
-rw-r--r--activerecord/test/cases/calculations_test.rb4
-rw-r--r--activerecord/test/cases/helper.rb4
-rw-r--r--activerecord/test/cases/log_subscriber_test.rb (renamed from activerecord/test/cases/subscriber_test.rb)11
-rw-r--r--activerecord/test/cases/method_scoping_test.rb10
-rw-r--r--activerecord/test/cases/pk_test.rb14
-rw-r--r--activerecord/test/models/author.rb9
-rw-r--r--activerecord/test/models/company.rb4
-rw-r--r--activerecord/test/models/developer.rb5
34 files changed, 420 insertions, 343 deletions
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 8a414a751b..e638da0f3e 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -5,25 +5,10 @@ require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require File.join(File.dirname(__FILE__), 'lib', 'active_record', 'version')
require File.expand_path(File.dirname(__FILE__)) + "/test/config"
-PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
-PKG_NAME = 'activerecord'
-PKG_VERSION = ActiveRecord::VERSION::STRING + PKG_BUILD
-PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
-
-RELEASE_NAME = "REL #{PKG_VERSION}"
-
-RUBY_FORGE_PROJECT = "activerecord"
-RUBY_FORGE_USER = "webster132"
-
MYSQL_DB_USER = 'rails'
-PKG_FILES = FileList[
- "lib/**/*", "test/**/*", "examples/**/*", "doc/**/*", "[A-Z]*", "install.rb", "Rakefile"
-].exclude(/\bCVS\b|~$/)
-
def run_without_aborting(*tasks)
errors = []
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index aeaafbb694..8b1ea8596a 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -1,9 +1,11 @@
+version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
+
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'activerecord'
- s.version = '3.0.0.beta1'
+ s.version = version
s.summary = 'Object-relational mapper framework (part of Rails).'
- s.description = 'Object-relational mapper framework (part of Rails).'
+ s.description = 'Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.'
s.required_ruby_version = '>= 1.8.7'
s.author = 'David Heinemeier Hansson'
@@ -18,7 +20,7 @@ Gem::Specification.new do |s|
s.extra_rdoc_files = %w( README )
s.rdoc_options.concat ['--main', 'README']
- s.add_dependency('activesupport', '= 3.0.0.beta1')
- s.add_dependency('activemodel', '= 3.0.0.beta1')
- s.add_dependency('arel', '~> 0.2.1')
+ s.add_dependency('activesupport', version)
+ s.add_dependency('activemodel', version)
+ s.add_dependency('arel', '~> 0.3.1')
end
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index b79da4565d..5942640c85 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -30,7 +30,6 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include
require 'active_support'
require 'active_model'
-require 'arel'
module ActiveRecord
extend ActiveSupport::Autoload
@@ -38,8 +37,8 @@ module ActiveRecord
eager_autoload do
autoload :VERSION
- autoload :ActiveRecordError, 'active_record/base'
- autoload :ConnectionNotEstablished, 'active_record/base'
+ autoload :ActiveRecordError, 'active_record/errors'
+ autoload :ConnectionNotEstablished, 'active_record/errors'
autoload :Aggregations
autoload :AssociationPreload
@@ -106,12 +105,16 @@ module ActiveRecord
eager_autoload do
autoload :AbstractAdapter
+ autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
end
end
autoload :TestCase
autoload :TestFixtures, 'active_record/fixtures'
+
+ base_hook do
+ Arel::Table.engine = Arel::Sql::Engine.new(self)
+ end
end
-Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)
-I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
+I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml' \ No newline at end of file
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index a5b06460fe..6725d4e88b 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -126,7 +126,7 @@ module ActiveRecord
parent_records.each do |parent_record|
association_proxy = parent_record.send(reflection_name)
association_proxy.loaded
- association_proxy.target.push *Array.wrap(associated_record)
+ association_proxy.target.push(*Array.wrap(associated_record))
association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 57785b4c93..b69577f8dd 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1537,58 +1537,42 @@ module ActiveRecord
# has_one associated objects, according to the defined :dependent rule.
def configure_dependency_for_has_one(reflection)
if reflection.options.include?(:dependent)
- case reflection.options[:dependent]
- when :destroy
- method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.destroy unless association.nil?
- end
- before_destroy method_name
- when :delete
- method_name = "has_one_dependent_delete_for_#{reflection.name}".to_sym
+ name = reflection.options[:dependent]
+ method_name = :"has_one_dependent_#{name}_for_#{reflection.name}"
+
+ case name
+ when :destroy, :delete
define_method(method_name) do
- # Retrieve the associated object and delete it. The retrieval
- # is necessary because there may be multiple associated objects
- # with foreign keys pointing to this object, and we only want
- # to delete the correct one, not all of them.
association = send(reflection.name)
- association.delete unless association.nil?
+ association.send(name) if association
end
- before_destroy method_name
when :nullify
- method_name = "has_one_dependent_nullify_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send(reflection.name)
- association.update_attribute(reflection.primary_key_name, nil) unless association.nil?
+ association.update_attribute(reflection.primary_key_name, nil) if association
end
- before_destroy method_name
else
raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})"
end
+
+ before_destroy method_name
end
end
def configure_dependency_for_belongs_to(reflection)
if reflection.options.include?(:dependent)
- case reflection.options[:dependent]
- when :destroy
- method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.destroy unless association.nil?
- end
- after_destroy method_name
- when :delete
- method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym
- define_method(method_name) do
- association = send(reflection.name)
- association.delete unless association.nil?
- end
- after_destroy method_name
- else
- raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
+ name = reflection.options[:dependent]
+
+ unless [:destroy, :delete].include?(name)
+ raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
+ end
+
+ method_name = :"belongs_to_dependent_#{name}_for_#{reflection.name}"
+ define_method(method_name) do
+ association = send(reflection.name)
+ association.send(name) if association
end
+ after_destroy method_name
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index 365fdeb55a..095814b635 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -39,6 +39,22 @@ module ActiveRecord
end
alias :primary_key= :set_primary_key
end
+
+ module InstanceMethods
+
+ # Returns this record's primary key value wrapped in an Array
+ # or nil if the record is a new_record?
+ # This is done to comply with the AMo interface that expects
+ # every AMo compliant object to respond_to?(:to_key) and return
+ # an Enumerable object from that call, or nil if new_record?
+ # This method also takes custom primary keys specified via
+ # the +set_primary_key+ into account.
+ def to_key
+ new_record? ? nil : [ self.primary_key ]
+ end
+
+ end
+
end
end
end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 318bfbe826..52587ef251 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -11,174 +11,12 @@ require 'active_support/core_ext/hash/deep_merge'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
-require 'active_support/core_ext/object/metaclass'
+require 'active_support/core_ext/object/singleton_class'
require 'active_support/core_ext/module/delegation'
+require 'arel'
+require 'active_record/errors'
module ActiveRecord #:nodoc:
- # Generic Active Record exception class.
- class ActiveRecordError < StandardError
- end
-
- # Raised when the single-table inheritance mechanism fails to locate the subclass
- # (for example due to improper usage of column that +inheritance_column+ points to).
- class SubclassNotFound < ActiveRecordError #:nodoc:
- end
-
- # Raised when an object assigned to an association has an incorrect type.
- #
- # class Ticket < ActiveRecord::Base
- # has_many :patches
- # end
- #
- # class Patch < ActiveRecord::Base
- # belongs_to :ticket
- # end
- #
- # # Comments are not patches, this assignment raises AssociationTypeMismatch.
- # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
- class AssociationTypeMismatch < ActiveRecordError
- end
-
- # Raised when unserialized object's type mismatches one specified for serializable field.
- class SerializationTypeMismatch < ActiveRecordError
- end
-
- # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
- class AdapterNotSpecified < ActiveRecordError
- end
-
- # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
- class AdapterNotFound < ActiveRecordError
- end
-
- # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
- class ConnectionNotEstablished < ActiveRecordError
- end
-
- # Raised when Active Record cannot find record by given id or set of ids.
- class RecordNotFound < ActiveRecordError
- end
-
- # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
- # saved because record is invalid.
- class RecordNotSaved < ActiveRecordError
- end
-
- # Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
- class StatementInvalid < ActiveRecordError
- end
-
- # Raised when SQL statement is invalid and the application gets a blank result.
- class ThrowResult < ActiveRecordError
- end
-
- # Parent class for all specific exceptions which wrap database driver exceptions
- # provides access to the original exception also.
- class WrappedDatabaseException < StatementInvalid
- attr_reader :original_exception
-
- def initialize(message, original_exception)
- super(message)
- @original_exception = original_exception
- end
- end
-
- # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
- class RecordNotUnique < WrappedDatabaseException
- end
-
- # Raised when a record cannot be inserted or updated because it references a non-existent record.
- class InvalidForeignKey < WrappedDatabaseException
- end
-
- # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
- # does not match number of expected variables.
- #
- # For example, in
- #
- # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
- #
- # two placeholders are given but only one variable to fill them.
- class PreparedStatementInvalid < ActiveRecordError
- end
-
- # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
- # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
- # the page before the other.
- #
- # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
- class StaleObjectError < ActiveRecordError
- end
-
- # Raised when association is being configured improperly or
- # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
- class ConfigurationError < ActiveRecordError
- end
-
- # Raised on attempt to update record that is instantiated as read only.
- class ReadOnlyRecord < ActiveRecordError
- end
-
- # <tt>ActiveRecord::Transactions::ClassMethods.transaction</tt> uses this exception
- # to distinguish a deliberate rollback from other exceptional situations.
- # Normally, raising an exception will cause the +transaction+ method to rollback
- # the database transaction *and* pass on the exception. But if you raise an
- # <tt>ActiveRecord::Rollback</tt> exception, then the database transaction will be rolled back,
- # without passing on the exception.
- #
- # For example, you could do this in your controller to rollback a transaction:
- #
- # class BooksController < ActionController::Base
- # def create
- # Book.transaction do
- # book = Book.new(params[:book])
- # book.save!
- # if today_is_friday?
- # # The system must fail on Friday so that our support department
- # # won't be out of job. We silently rollback this transaction
- # # without telling the user.
- # raise ActiveRecord::Rollback, "Call tech support!"
- # end
- # end
- # # ActiveRecord::Rollback is the only exception that won't be passed on
- # # by ActiveRecord::Base.transaction, so this line will still be reached
- # # even on Friday.
- # redirect_to root_url
- # end
- # end
- class Rollback < ActiveRecordError
- end
-
- # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
- class DangerousAttributeError < ActiveRecordError
- end
-
- # Raised when unknown attributes are supplied via mass assignment.
- class UnknownAttributeError < NoMethodError
- end
-
- # Raised when an error occurred while doing a mass assignment to an attribute through the
- # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
- # offending attribute.
- class AttributeAssignmentError < ActiveRecordError
- attr_reader :exception, :attribute
- def initialize(message, exception, attribute)
- @exception = exception
- @attribute = attribute
- @message = message
- end
- end
-
- # Raised when there are multiple errors while doing a mass assignment through the +attributes+
- # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
- # objects, each corresponding to the error while assigning to an attribute.
- class MultiparameterAssignmentErrors < ActiveRecordError
- attr_reader :errors
- def initialize(errors)
- @errors = errors
- end
- end
-
# Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
# which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
# is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain
@@ -551,8 +389,8 @@ module ActiveRecord #:nodoc:
class << self # Class methods
def colorize_logging(*args)
ActiveSupport::Deprecation.warn "ActiveRecord::Base.colorize_logging and " <<
- "config.active_record.colorize_logging are deprecated. Please use " <<
- "Rails::Subscriber.colorize_logging or config.colorize_logging instead", caller
+ "config.active_record.colorize_logging are deprecated. Please use " <<
+ "Rails::LogSubscriber.colorize_logging or config.colorize_logging instead", caller
end
alias :colorize_logging= :colorize_logging
@@ -1669,12 +1507,12 @@ module ActiveRecord #:nodoc:
@attributes_cache = {}
@new_record = true
ensure_proper_type
- self.attributes = attributes unless attributes.nil?
if scope = self.class.send(:current_scoped_methods)
create_with = scope.scope_for_create
create_with.each { |att,value| self.send("#{att}=", value) } if create_with
end
+ self.attributes = attributes unless attributes.nil?
result = yield self if block_given?
_run_initialize_callbacks
@@ -1767,6 +1605,11 @@ module ActiveRecord #:nodoc:
@destroyed || false
end
+ # Returns if the record is persisted, i.e. it's not a new record and it was not destroyed.
+ def persisted?
+ !(new_record? || destroyed?)
+ end
+
# :call-seq:
# save(options)
#
@@ -1816,7 +1659,7 @@ module ActiveRecord #:nodoc:
# callbacks, Observer methods, or any <tt>:dependent</tt> association
# options, use <tt>#destroy</tt>.
def delete
- self.class.delete(id) unless new_record?
+ self.class.delete(id) if persisted?
@destroyed = true
freeze
end
@@ -1824,7 +1667,7 @@ module ActiveRecord #:nodoc:
# Deletes the record in the database and freezes this instance to reflect that no changes should
# be made (since they can't be persisted).
def destroy
- unless new_record?
+ if persisted?
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
end
@@ -1844,6 +1687,7 @@ module ActiveRecord #:nodoc:
became.instance_variable_set("@attributes", @attributes)
became.instance_variable_set("@attributes_cache", @attributes_cache)
became.instance_variable_set("@new_record", new_record?)
+ became.instance_variable_set("@destroyed", destroyed?)
became
end
@@ -1926,7 +1770,7 @@ module ActiveRecord #:nodoc:
def reload(options = nil)
clear_aggregation_cache
clear_association_cache
- @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
+ @attributes.update(self.class.send(:with_exclusive_scope) { self.class.find(self.id, options) }.instance_variable_get('@attributes'))
@attributes_cache = {}
self
end
@@ -1995,10 +1839,9 @@ module ActiveRecord #:nodoc:
# Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
def attributes
- self.attribute_names.inject({}) do |attrs, name|
- attrs[name] = read_attribute(name)
- attrs
- end
+ attrs = {}
+ attribute_names.each { |name| attrs[name] = read_attribute(name) }
+ attrs
end
# Returns an <tt>#inspect</tt>-like string for the value of the
@@ -2042,8 +1885,7 @@ module ActiveRecord #:nodoc:
def ==(comparison_object)
comparison_object.equal?(self) ||
(comparison_object.instance_of?(self.class) &&
- comparison_object.id == id &&
- !comparison_object.new_record?)
+ comparison_object.id == id && !comparison_object.new_record?)
end
# Delegates to ==
@@ -2343,7 +2185,7 @@ module ActiveRecord #:nodoc:
# Returns a comma-separated pair list, like "key1 = val1, key2 = val2".
def comma_pair_list(hash)
- hash.inject([]) { |list, pair| list << "#{pair.first} = #{pair.last}" }.join(", ")
+ hash.map { |k,v| "#{k} = #{v}" }.join(", ")
end
def quote_columns(quoter, hash)
@@ -2397,8 +2239,10 @@ module ActiveRecord #:nodoc:
include Aggregations, Transactions, Reflection, Serialization
+ NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner)
end
end
# TODO: Remove this and make it work with LAZY flag
require 'active_record/connection_adapters/abstract_adapter'
+ActiveRecord.run_base_hooks(ActiveRecord::Base) \ No newline at end of file
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index 027d736484..abb695264e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -113,7 +113,7 @@ module ActiveRecord
def transaction(options = {})
options.assert_valid_keys :requires_new, :joinable
- last_transaction_joinable = @transaction_joinable
+ last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
if options.has_key?(:joinable)
@transaction_joinable = options[:joinable]
else
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 520f3c8c0c..64faaef4a0 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -319,16 +319,19 @@ module ActiveRecord
def method_missing(symbol, *args)
if symbol.to_s == 'xml'
xml_column_fallback(args)
+ else
+ super
end
end
def xml_column_fallback(*args)
case @base.adapter_name.downcase
- when 'sqlite', 'mysql'
- options = args.extract_options!
- column(args[0], :text, options)
- end
+ when 'sqlite', 'mysql'
+ options = args.extract_options!
+ column(args[0], :text, options)
end
+ end
+
# Appends a primary key definition to the table definition.
# Can be called multiple times, but this is probably not a good idea.
def primary_key(name)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 7e80347f75..6ffffc8654 100755
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -37,6 +37,7 @@ module ActiveRecord
@@row_even = true
def initialize(connection, logger = nil) #:nodoc:
+ @active = nil
@connection, @logger = connection, logger
@runtime = 0
@query_cache_enabled = false
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
new file mode 100644
index 0000000000..cf5ddca2ba
--- /dev/null
+++ b/activerecord/lib/active_record/errors.rb
@@ -0,0 +1,165 @@
+module ActiveRecord
+ # Generic Active Record exception class.
+ class ActiveRecordError < StandardError
+ end
+
+ # Raised when the single-table inheritance mechanism fails to locate the subclass
+ # (for example due to improper usage of column that +inheritance_column+ points to).
+ class SubclassNotFound < ActiveRecordError #:nodoc:
+ end
+
+ # Raised when an object assigned to an association has an incorrect type.
+ #
+ # class Ticket < ActiveRecord::Base
+ # has_many :patches
+ # end
+ #
+ # class Patch < ActiveRecord::Base
+ # belongs_to :ticket
+ # end
+ #
+ # # Comments are not patches, this assignment raises AssociationTypeMismatch.
+ # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
+ class AssociationTypeMismatch < ActiveRecordError
+ end
+
+ # Raised when unserialized object's type mismatches one specified for serializable field.
+ class SerializationTypeMismatch < ActiveRecordError
+ end
+
+ # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
+ class AdapterNotSpecified < ActiveRecordError
+ end
+
+ # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
+ class AdapterNotFound < ActiveRecordError
+ end
+
+ # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
+ class ConnectionNotEstablished < ActiveRecordError
+ end
+
+ # Raised when Active Record cannot find record by given id or set of ids.
+ class RecordNotFound < ActiveRecordError
+ end
+
+ # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
+ # saved because record is invalid.
+ class RecordNotSaved < ActiveRecordError
+ end
+
+ # Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
+ class StatementInvalid < ActiveRecordError
+ end
+
+ # Raised when SQL statement is invalid and the application gets a blank result.
+ class ThrowResult < ActiveRecordError
+ end
+
+ # Parent class for all specific exceptions which wrap database driver exceptions
+ # provides access to the original exception also.
+ class WrappedDatabaseException < StatementInvalid
+ attr_reader :original_exception
+
+ def initialize(message, original_exception)
+ super(message)
+ @original_exception = original_exception
+ end
+ end
+
+ # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
+ class RecordNotUnique < WrappedDatabaseException
+ end
+
+ # Raised when a record cannot be inserted or updated because it references a non-existent record.
+ class InvalidForeignKey < WrappedDatabaseException
+ end
+
+ # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
+ # does not match number of expected variables.
+ #
+ # For example, in
+ #
+ # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
+ #
+ # two placeholders are given but only one variable to fill them.
+ class PreparedStatementInvalid < ActiveRecordError
+ end
+
+ # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
+ # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
+ # the page before the other.
+ #
+ # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
+ class StaleObjectError < ActiveRecordError
+ end
+
+ # Raised when association is being configured improperly or
+ # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
+ class ConfigurationError < ActiveRecordError
+ end
+
+ # Raised on attempt to update record that is instantiated as read only.
+ class ReadOnlyRecord < ActiveRecordError
+ end
+
+ # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
+ # to distinguish a deliberate rollback from other exceptional situations.
+ # Normally, raising an exception will cause the +transaction+ method to rollback
+ # the database transaction *and* pass on the exception. But if you raise an
+ # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
+ # without passing on the exception.
+ #
+ # For example, you could do this in your controller to rollback a transaction:
+ #
+ # class BooksController < ActionController::Base
+ # def create
+ # Book.transaction do
+ # book = Book.new(params[:book])
+ # book.save!
+ # if today_is_friday?
+ # # The system must fail on Friday so that our support department
+ # # won't be out of job. We silently rollback this transaction
+ # # without telling the user.
+ # raise ActiveRecord::Rollback, "Call tech support!"
+ # end
+ # end
+ # # ActiveRecord::Rollback is the only exception that won't be passed on
+ # # by ActiveRecord::Base.transaction, so this line will still be reached
+ # # even on Friday.
+ # redirect_to root_url
+ # end
+ # end
+ class Rollback < ActiveRecordError
+ end
+
+ # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
+ class DangerousAttributeError < ActiveRecordError
+ end
+
+ # Raised when unknown attributes are supplied via mass assignment.
+ class UnknownAttributeError < NoMethodError
+ end
+
+ # Raised when an error occurred while doing a mass assignment to an attribute through the
+ # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
+ # offending attribute.
+ class AttributeAssignmentError < ActiveRecordError
+ attr_reader :exception, :attribute
+ def initialize(message, exception, attribute)
+ @exception = exception
+ @attribute = attribute
+ @message = message
+ end
+ end
+
+ # Raised when there are multiple errors while doing a mass assignment through the +attributes+
+ # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
+ # objects, each corresponding to the error while assigning to an attribute.
+ class MultiparameterAssignmentErrors < ActiveRecordError
+ attr_reader :errors
+ def initialize(errors)
+ @errors = errors
+ end
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 068d2a25b2..fd5ffc6d77 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/object/metaclass'
+require 'active_support/core_ext/object/singleton_class'
module ActiveRecord
# Exception that can be raised to stop migrations from going backwards.
@@ -303,7 +303,7 @@ module ActiveRecord
case sym
when :up, :down
- metaclass.send(:alias_method_chain, sym, "benchmarks")
+ singleton_class.send(:alias_method_chain, sym, "benchmarks")
end
ensure
@ignore_new_methods = false
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index ff6c041ef4..394e1587e1 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -1,6 +1,6 @@
require 'active_support/core_ext/array'
require 'active_support/core_ext/hash/except'
-require 'active_support/core_ext/object/metaclass'
+require 'active_support/core_ext/object/singleton_class'
module ActiveRecord
module NamedScope
@@ -26,7 +26,7 @@ module ActiveRecord
if options.present?
Scope.init(self, options, &block)
else
- current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.spawn
+ current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
end
end
@@ -112,7 +112,7 @@ module ActiveRecord
options.call(*args)
end, &block)
end
- metaclass.instance_eval do
+ singleton_class.instance_eval do
define_method name do |*args|
scopes[name].call(self, *args)
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index e70b0d1bfb..60addd46c6 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -20,35 +20,43 @@ module ActiveRecord
end
# TODO If we require the wrong file, the error never comes up.
- require "active_record/railties/subscriber"
- subscriber ActiveRecord::Railties::Subscriber.new
+ require "active_record/railties/log_subscriber"
+ log_subscriber ActiveRecord::Railties::LogSubscriber.new
initializer "active_record.initialize_timezone" do
- ActiveRecord::Base.time_zone_aware_attributes = true
- ActiveRecord::Base.default_timezone = :utc
+ ActiveRecord.base_hook do
+ self.time_zone_aware_attributes = true
+ self.default_timezone = :utc
+ end
end
initializer "active_record.logger" do
- ActiveRecord::Base.logger ||= ::Rails.logger
+ ActiveRecord.base_hook { self.logger ||= ::Rails.logger }
end
initializer "active_record.set_configs" do |app|
- app.config.active_record.each do |k,v|
- ActiveRecord::Base.send "#{k}=", v
+ ActiveRecord.base_hook do
+ app.config.active_record.each do |k,v|
+ send "#{k}=", v
+ end
end
end
# This sets the database configuration from Configuration#database_configuration
# and then establishes the connection.
initializer "active_record.initialize_database" do |app|
- ActiveRecord::Base.configurations = app.config.database_configuration
- ActiveRecord::Base.establish_connection
+ ActiveRecord.base_hook do
+ self.configurations = app.config.database_configuration
+ establish_connection
+ end
end
# Expose database runtime to controller for logging.
initializer "active_record.log_runtime" do |app|
require "active_record/railties/controller_runtime"
- ActionController::Base.send :include, ActiveRecord::Railties::ControllerRuntime
+ ActionController.base_hook do
+ include ActiveRecord::Railties::ControllerRuntime
+ end
end
# Setup database middleware after initializers have run
@@ -64,18 +72,22 @@ module ActiveRecord
end
initializer "active_record.load_observers" do
- ActiveRecord::Base.instantiate_observers
+ ActiveRecord.base_hook { instantiate_observers }
- ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do
- ActiveRecord::Base.instantiate_observers
+ ActiveRecord.base_hook do
+ ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do
+ ActiveRecord::Base.instantiate_observers
+ end
end
end
initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
- unless app.config.cache_classes
- ActionDispatch::Callbacks.after do
- ActiveRecord::Base.reset_subclasses
- ActiveRecord::Base.clear_reloadable_connections!
+ ActiveRecord.base_hook do
+ unless app.config.cache_classes
+ ActionDispatch::Callbacks.after do
+ ActiveRecord::Base.reset_subclasses
+ ActiveRecord::Base.clear_reloadable_connections!
+ end
end
end
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index ed7d2a045e..fa6caa4910 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -109,7 +109,7 @@ namespace :db do
# Only connect to local databases
local_database?(config) { drop_database(config) }
rescue Exception => e
- puts "Couldn't drop #{config['database']} : #{e.inspect}"
+ $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
end
end
end
@@ -121,7 +121,7 @@ namespace :db do
begin
drop_database(config)
rescue Exception => e
- puts "Couldn't drop #{config['database']} : #{e.inspect}"
+ $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
end
end
@@ -129,7 +129,7 @@ namespace :db do
if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?
yield
else
- puts "This task only modifies local databases. #{config['database']} is on a remote host."
+ $stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
end
end
@@ -204,7 +204,7 @@ namespace :db do
ActiveRecord::Base.establish_connection(config)
puts ActiveRecord::Base.connection.encoding
else
- puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
end
end
@@ -216,7 +216,7 @@ namespace :db do
ActiveRecord::Base.establish_connection(config)
puts ActiveRecord::Base.connection.collation
else
- puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
end
end
diff --git a/activerecord/lib/active_record/railties/subscriber.rb b/activerecord/lib/active_record/railties/log_subscriber.rb
index fd873dbff8..48b25032ce 100644
--- a/activerecord/lib/active_record/railties/subscriber.rb
+++ b/activerecord/lib/active_record/railties/log_subscriber.rb
@@ -1,6 +1,6 @@
module ActiveRecord
module Railties
- class Subscriber < Rails::Subscriber
+ class LogSubscriber < Rails::LogSubscriber
def sql(event)
name = '%s (%.1fms)' % [event.payload[:name], event.duration]
sql = event.payload[:sql].squeeze(' ')
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 7bc3d3bf33..aca4629dd8 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -21,6 +21,10 @@ module ActiveRecord
with_create_scope { @klass.new(*args, &block) }
end
+ def initialize_copy(other)
+ reset
+ end
+
alias build new
def create(*args, &block)
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 65e5c0495c..7e83eccbb5 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -20,7 +20,7 @@ module ActiveRecord
table = Arel::Table.new(table_name, :engine => @engine)
end
- attribute = table[column] || Arel::Attribute.new(table, column.to_sym)
+ attribute = table[column]
case value
when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 0266700f66..e00d9cdf27 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -8,7 +8,7 @@ module ActiveRecord
class_eval <<-CEVAL
def #{query_method}(*args)
- new_relation = spawn
+ new_relation = clone
value = Array.wrap(args.flatten).reject {|x| x.blank? }
new_relation.#{query_method}_values += value if value.present?
new_relation
@@ -19,7 +19,7 @@ module ActiveRecord
[:where, :having].each do |query_method|
class_eval <<-CEVAL
def #{query_method}(*args)
- new_relation = spawn
+ new_relation = clone
value = build_where(*args)
new_relation.#{query_method}_values += [*value] if value.present?
new_relation
@@ -32,7 +32,7 @@ module ActiveRecord
class_eval <<-CEVAL
def #{query_method}(value = true)
- new_relation = spawn
+ new_relation = clone
new_relation.#{query_method}_value = value
new_relation
end
@@ -41,12 +41,12 @@ module ActiveRecord
end
def lock(locks = true)
- relation = spawn
+ relation = clone
case locks
when String, TrueClass, NilClass
- spawn.tap {|new_relation| new_relation.lock_value = locks || true }
+ clone.tap {|new_relation| new_relation.lock_value = locks || true }
else
- spawn.tap {|new_relation| new_relation.lock_value = false }
+ clone.tap {|new_relation| new_relation.lock_value = false }
end
end
@@ -174,7 +174,7 @@ module ActiveRecord
arel = arel.lock
when String
arel = arel.lock(@lock_value)
- end
+ end if defined?(@lock_value)
arel
end
@@ -184,16 +184,16 @@ module ActiveRecord
builder = PredicateBuilder.new(table.engine)
- conditions = if [String, Array].include?(args.first.class)
- @klass.send(:sanitize_sql, args.size > 1 ? args : args.first)
- elsif args.first.is_a?(Hash)
- attributes = @klass.send(:expand_hash_conditions_for_aggregates, args.first)
+ opts = args.first
+ case opts
+ when String, Array
+ @klass.send(:sanitize_sql, args.size > 1 ? args : opts)
+ when Hash
+ attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
builder.build_from_hash(attributes, table)
else
- args.first
+ opts
end
-
- conditions
end
private
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index cccf413e67..a18380f01c 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -1,11 +1,7 @@
module ActiveRecord
module SpawnMethods
- def spawn
- clone.reset
- end
-
def merge(r)
- merged_relation = spawn
+ merged_relation = clone
return merged_relation unless r
merged_relation = merged_relation.eager_load(r.eager_load_values).preload(r.preload_values).includes(r.includes_values)
@@ -83,7 +79,7 @@ module ActiveRecord
:order, :select, :readonly, :group, :having, :from, :lock ]
def apply_finder_options(options)
- relation = spawn
+ relation = clone
return relation unless options
options.assert_valid_keys(VALID_FIND_OPTIONS)
diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb
index 286ecd0289..eaf5dc6545 100644
--- a/activerecord/lib/active_record/version.rb
+++ b/activerecord/lib/active_record/version.rb
@@ -2,8 +2,9 @@ module ActiveRecord
module VERSION #:nodoc:
MAJOR = 3
MINOR = 0
- TINY = "0.beta1"
+ TINY = 0
+ BUILD = "beta1"
- STRING = [MAJOR, MINOR, TINY].join('.')
+ STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
end
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index 4c1589d965..665c387d5d 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -27,6 +27,16 @@ if ActiveRecord::Base.connection.supports_migrations?
assert_nothing_raised { @connection.select_all "SELECT * FROM schema_migrations" }
assert_equal 7, ActiveRecord::Migrator::current_version
end
+
+ def test_schema_raises_an_error_for_invalid_column_ntype
+ assert_raise NoMethodError do
+ ActiveRecord::Schema.define(:version => 8) do
+ create_table :vegetables do |t|
+ t.unknown :color
+ end
+ end
+ end
+ end
end
end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 2a77eed1b5..41a23d7f61 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -18,7 +18,8 @@ require 'models/essay'
class BelongsToAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :topics,
- :developers_projects, :computers, :authors, :posts, :tags, :taggings, :comments
+ :developers_projects, :computers, :authors, :author_addresses,
+ :posts, :tags, :taggings, :comments
def test_belongs_to
Client.find(3).firm.name
@@ -346,14 +347,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
assert companies(:first_client).readonly_firm.readonly?
end
-
+
def test_polymorphic_assignment_foreign_type_field_updating
# should update when assigning a saved record
sponsor = Sponsor.new
member = Member.create
sponsor.sponsorable = member
assert_equal "Member", sponsor.sponsorable_type
-
+
# should update when assigning a new record
sponsor = Sponsor.new
member = Member.new
@@ -374,15 +375,15 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
essay.writer = writer
assert_equal "Author", essay.writer_type
end
-
+
def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
sponsor = Sponsor.new
saved_member = Member.create
new_member = Member.new
-
+
sponsor.sponsorable = saved_member
assert_equal saved_member.id, sponsor.sponsorable_id
-
+
sponsor.sponsorable = new_member
assert_equal nil, sponsor.sponsorable_id
end
@@ -424,4 +425,23 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
Account.find(@account.id, :include => :firm).save!
end
end
+
+ def test_dependent_delete_and_destroy_with_belongs_to
+ author_address = author_addresses(:david_address)
+ author_address_extra = author_addresses(:david_address_extra)
+ assert_equal [], AuthorAddress.destroyed_author_address_ids
+
+ assert_difference "AuthorAddress.count", -2 do
+ authors(:david).destroy
+ end
+
+ assert_equal [], AuthorAddress.find_all_by_id([author_address.id, author_address_extra.id])
+ assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids
+ end
+
+ def test_invalid_belongs_to_dependent_option_raises_exception
+ assert_raise ArgumentError do
+ Author.belongs_to :special_author_address, :dependent => :nullify
+ end
+ end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index ce7eedbb54..54624e79ce 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -14,7 +14,7 @@ require 'models/tagging'
class HasManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :categories, :companies, :developers, :projects,
- :developers_projects, :topics, :authors, :comments, :author_addresses,
+ :developers_projects, :topics, :authors, :comments,
:people, :posts, :readers, :taggings
def setup
@@ -684,24 +684,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal 'Microsoft', another_ms_client.name
end
- def test_dependent_delete_and_destroy_with_belongs_to
- author_address = author_addresses(:david_address)
- assert_equal [], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
-
- assert_difference "AuthorAddress.count", -2 do
- authors(:david).destroy
- end
-
- assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_id)
- assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_extra_id)
- end
-
- def test_invalid_belongs_to_dependent_option_raises_exception
- assert_raise ArgumentError do
- Author.belongs_to :special_author_address, :dependent => :nullify
- end
- end
-
def test_clearing_without_initial_access
firm = companies(:first_firm)
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index d359ad48c5..d5dbb88886 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -14,7 +14,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_equal companies(:first_firm).account, Account.find(1)
assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
end
-
+
def test_has_one_cache_nils
firm = companies(:another_firm)
assert_queries(1) { assert_nil firm.account }
@@ -96,7 +96,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_nil Account.find(old_account_id).firm_id
end
- def test_association_changecalls_delete
+ def test_association_change_calls_delete
companies(:first_firm).deletable_account = Account.new
assert_equal [], Account.destroyed_account_ids[companies(:first_firm).id]
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 1441b4278d..e3047fe873 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1330,11 +1330,6 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_destroyed_returns_boolean
- developer = Developer.new
- assert_equal developer.destroyed?, false
- developer.destroy
- assert_equal developer.destroyed?, true
-
developer = Developer.first
assert_equal developer.destroyed?, false
developer.destroy
@@ -1346,6 +1341,23 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal developer.destroyed?, true
end
+ def test_persisted_returns_boolean
+ developer = Developer.new(:name => "Jose")
+ assert_equal developer.persisted?, false
+ developer.save!
+ assert_equal developer.persisted?, true
+
+ developer = Developer.first
+ assert_equal developer.persisted?, true
+ developer.destroy
+ assert_equal developer.persisted?, false
+
+ developer = Developer.last
+ assert_equal developer.persisted?, true
+ developer.delete
+ assert_equal developer.persisted?, false
+ end
+
def test_clone
topic = Topic.find(1)
cloned_topic = nil
@@ -1711,6 +1723,12 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal t1.title, t2.title
end
+ def test_reload_with_exclusive_scope
+ dev = DeveloperCalledDavid.first
+ dev.update_attributes!( :name => "NotDavid" )
+ assert_equal dev, dev.reload
+ end
+
def test_define_attr_method_with_value
k = Class.new( ActiveRecord::Base )
k.send(:define_attr_method, :table_name, "foo")
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index e6d56a7193..28a1ae5feb 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -38,12 +38,12 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_should_get_maximum_of_field_with_include
- assert_equal 50, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
+ assert_equal 55, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
end
def test_should_get_maximum_of_field_with_scoped_include
Account.send :with_scope, :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
- assert_equal 50, Account.maximum(:credit_limit)
+ assert_equal 55, Account.maximum(:credit_limit)
end
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 9e8bfbbee8..e831ebf36c 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -1,11 +1,15 @@
require File.expand_path('../../../../load_paths', __FILE__)
+lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
require 'config'
require 'test/unit'
require 'stringio'
require 'active_record'
+require 'active_support/dependencies'
require 'connection'
begin
diff --git a/activerecord/test/cases/subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb
index 5328d4468b..f3b94eb829 100644
--- a/activerecord/test/cases/subscriber_test.rb
+++ b/activerecord/test/cases/log_subscriber_test.rb
@@ -1,15 +1,16 @@
require "cases/helper"
require "models/developer"
-require "rails/subscriber/test_helper"
-require "active_record/railties/subscriber"
+require "rails/log_subscriber/test_helper"
+require "active_record/railties/log_subscriber"
-class SubscriberTest < ActiveSupport::TestCase
- include Rails::Subscriber::TestHelper
- Rails::Subscriber.add(:active_record, ActiveRecord::Railties::Subscriber.new)
+class LogSubscriberTest < ActiveSupport::TestCase
+ include Rails::LogSubscriber::TestHelper
def setup
@old_logger = ActiveRecord::Base.logger
super
+
+ Rails::LogSubscriber.add(:active_record, ActiveRecord::Railties::LogSubscriber.new)
end
def teardown
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index 1081aa40a9..3151457440 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -663,6 +663,16 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal 2, posts.count
assert_equal posts(:thinking), posts.first
end
+
+ def test_create_attribute_overwrites_default_scoping
+ assert_equal 'David', PoorDeveloperCalledJamis.create!(:name => 'David').name
+ assert_equal 200000, PoorDeveloperCalledJamis.create!(:name => 'David', :salary => 200000).salary
+ end
+
+ def test_create_attribute_overwrites_default_values
+ assert_equal nil, PoorDeveloperCalledJamis.create!(:salary => nil).salary
+ assert_equal 50000, PoorDeveloperCalledJamis.create!(:name => 'David').salary
+ end
end
=begin
diff --git a/activerecord/test/cases/pk_test.rb b/activerecord/test/cases/pk_test.rb
index c121e0aa0f..5bba1d5625 100644
--- a/activerecord/test/cases/pk_test.rb
+++ b/activerecord/test/cases/pk_test.rb
@@ -9,6 +9,20 @@ require 'models/mixed_case_monkey'
class PrimaryKeysTest < ActiveRecord::TestCase
fixtures :topics, :subscribers, :movies, :mixed_case_monkeys
+ def test_to_key_with_default_primary_key
+ topic = Topic.new
+ assert topic.to_key.nil?
+ topic = Topic.find(1)
+ assert_equal topic.to_key, [1]
+ end
+
+ def test_to_key_with_customized_primary_key
+ keyboard = Keyboard.new
+ assert keyboard.to_key.nil?
+ keyboard.save
+ assert_equal keyboard.to_key, [keyboard.id]
+ end
+
def test_integer_key
topic = Topic.find(1)
assert_equal(topics(:first).author_name, topic.author_name)
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 7cbc6e803f..025f6207f8 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -35,7 +35,7 @@ class Author < ActiveRecord::Base
has_many :ordered_uniq_comments, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id'
has_many :ordered_uniq_comments_desc, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id DESC'
has_many :readonly_comments, :through => :posts, :source => :comments, :readonly => true
-
+
has_many :special_posts
has_many :special_post_comments, :through => :special_posts, :source => :comments
@@ -130,14 +130,11 @@ class AuthorAddress < ActiveRecord::Base
has_one :author
def self.destroyed_author_address_ids
- @destroyed_author_address_ids ||= Hash.new { |h,k| h[k] = [] }
+ @destroyed_author_address_ids ||= []
end
before_destroy do |author_address|
- if author_address.author
- AuthorAddress.destroyed_author_address_ids[author_address.author.id] << author_address.id
- end
- true
+ AuthorAddress.destroyed_author_address_ids << author_address.id
end
end
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index df5fd10b6b..f31d5f87e5 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -82,7 +82,7 @@ class Firm < Company
has_one :account_using_primary_key, :primary_key => "firm_id", :class_name => "Account", :order => "id"
has_one :account_using_foreign_and_primary_keys, :foreign_key => "firm_name", :primary_key => "name", :class_name => "Account"
has_one :deletable_account, :foreign_key => "firm_id", :class_name => "Account", :dependent => :delete
-
+
has_one :account_limit_500_with_hash_conditions, :foreign_key => "firm_id", :class_name => "Account", :conditions => { :credit_limit => 500 }
has_one :unautosaved_account, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false
@@ -155,7 +155,7 @@ class VerySpecialClient < SpecialClient
end
class Account < ActiveRecord::Base
- belongs_to :firm
+ belongs_to :firm, :class_name => 'Company'
belongs_to :unautosaved_firm, :foreign_key => "firm_id", :class_name => "Firm", :autosave => false
def self.destroyed_account_ids
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index e7a1e110d7..e35de3b9b0 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -99,3 +99,8 @@ class DeveloperCalledJamis < ActiveRecord::Base
self.table_name = 'developers'
default_scope :conditions => { :name => 'Jamis' }
end
+
+class PoorDeveloperCalledJamis < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :conditions => { :name => 'Jamis', :salary => 50000 }
+end \ No newline at end of file