aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/association_preload.rb20
-rwxr-xr-xactiverecord/lib/active_record/associations.rb23
-rw-r--r--activerecord/lib/active_record/associations/association_proxy.rb14
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb7
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb2
-rwxr-xr-xactiverecord/lib/active_record/base.rb1
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb34
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/lib/active_record/notifications.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb10
-rw-r--r--activerecord/lib/active_record/validations.rb2
11 files changed, 47 insertions, 72 deletions
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index e41fda7a4b..9f7b2a60b2 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/enumerable'
+
module ActiveRecord
# See ActiveRecord::AssociationPreload::ClassMethods for documentation.
module AssociationPreload #:nodoc:
@@ -82,7 +85,7 @@ module ActiveRecord
# only one level deep in the +associations+ argument, i.e. it's not passed
# to the child associations when +associations+ is a Hash.
def preload_associations(records, associations, preload_options={})
- records = [records].flatten.compact.uniq
+ records = Array.wrap(records).compact.uniq
return if records.empty?
case associations
when Array then associations.each {|association| preload_associations(records, association, preload_options)}
@@ -92,7 +95,7 @@ module ActiveRecord
raise "parent must be an association name" unless parent.is_a?(String) || parent.is_a?(Symbol)
preload_associations(records, parent, preload_options)
reflection = reflections[parent]
- parents = records.map {|record| record.send(reflection.name)}.flatten.compact
+ parents = records.sum { |record| Array.wrap(record.send(reflection.name)) }
unless parents.empty?
parents.first.class.preload_associations(parents, child)
end
@@ -123,7 +126,8 @@ module ActiveRecord
parent_records.each do |parent_record|
association_proxy = parent_record.send(reflection_name)
association_proxy.loaded
- association_proxy.target.push(*[associated_record].flatten)
+ association_proxy.target.push *Array.wrap(associated_record)
+
association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end
end
@@ -254,6 +258,7 @@ module ActiveRecord
through_reflection = reflections[through_association]
through_primary_key = through_reflection.primary_key_name
+ through_records = []
if reflection.options[:source_type]
interface = reflection.source_reflection.options[:foreign_type]
preload_options = {:conditions => ["#{connection.quote_column_name interface} = ?", reflection.options[:source_type]]}
@@ -262,23 +267,22 @@ module ActiveRecord
records.first.class.preload_associations(records, through_association, preload_options)
# Dont cache the association - we would only be caching a subset
- through_records = []
records.each do |record|
proxy = record.send(through_association)
if proxy.respond_to?(:target)
- through_records << proxy.target
+ through_records.concat Array.wrap(proxy.target)
proxy.reset
else # this is a has_one :through reflection
through_records << proxy if proxy
end
end
- through_records.flatten!
else
records.first.class.preload_associations(records, through_association)
- through_records = records.map {|record| record.send(through_association)}.flatten
+ records.each do |record|
+ through_records.concat Array.wrap(record.send(through_association))
+ end
end
- through_records.compact!
through_records
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 03c8d4b3ed..fc6f15206a 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/enumerable'
module ActiveRecord
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
@@ -1396,8 +1397,8 @@ module ActiveRecord
end
define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
- ids = (new_value || []).reject { |nid| nid.blank? }
- send("#{reflection.name}=", reflection.klass.find(ids))
+ ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i)
+ send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids))
end
end
end
@@ -1480,7 +1481,7 @@ module ActiveRecord
if reflection.options.include?(:dependent)
# Add polymorphic type if the :as option is present
dependent_conditions = []
- dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}"
+ dependent_conditions << "#{reflection.primary_key_name} = \#{record.#{reflection.name}.send(:owner_quoted_id)}"
dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.quoted_table_name) if reflection.options[:conditions]
dependent_conditions << extra_conditions if extra_conditions
@@ -1922,12 +1923,16 @@ module ActiveRecord
reflection = base.reflections[name]
is_collection = [:has_many, :has_and_belongs_to_many].include?(reflection.macro)
- parent_records = records.map do |record|
- descendant = record.send(reflection.name)
- next unless descendant
- descendant.target.uniq! if is_collection
- descendant
- end.flatten.compact
+ parent_records = []
+ records.each do |record|
+ if descendant = record.send(reflection.name)
+ if is_collection
+ parent_records.concat descendant.target.uniq
+ else
+ parent_records << descendant
+ end
+ end
+ end
remove_duplicate_results!(reflection.klass, parent_records, associations[name]) unless parent_records.empty?
end
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 75218c01d2..7d8f4670fa 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -256,10 +256,16 @@ module ActiveRecord
end
end
- # Array#flatten has problems with recursive arrays. Going one level
- # deeper solves the majority of the problems.
- def flatten_deeper(array)
- array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
+ if RUBY_VERSION < '1.9.2'
+ # Array#flatten has problems with recursive arrays before Ruby 1.9.2.
+ # Going one level deeper solves the majority of the problems.
+ def flatten_deeper(array)
+ array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
+ end
+ else
+ def flatten_deeper(array)
+ array.flatten
+ end
end
# Returns the ID of the owner, quoted if needed.
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index ab7ad34b9e..3a9a67e3a2 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -31,11 +31,10 @@ module ActiveRecord
self.class.define_attribute_methods
method_name = method_id.to_s
guard_private_attribute_method!(method_name, args)
- if self.class.generated_attribute_methods.instance_methods.include?(method_name)
- return self.send(method_id, *args, &block)
- end
+ send(method_id, *args, &block)
+ else
+ super
end
- super
end
def respond_to?(*args)
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 4df0f1af69..4a3ab9ea82 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/object/tap'
-
module ActiveRecord
module AttributeMethods
module Dirty
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4e6090458a..056f29f029 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -12,7 +12,6 @@ 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/symbol'
require 'active_support/core_ext/object/metaclass'
module ActiveRecord #:nodoc:
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index c8cd79a2b0..986bc7009b 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -23,16 +23,6 @@ module ActiveRecord
# p2.first_name = "should fail"
# p2.save # Raises a ActiveRecord::StaleObjectError
#
- # Optimistic locking will also check for stale data when objects are destroyed. Example:
- #
- # p1 = Person.find(1)
- # p2 = Person.find(1)
- #
- # p1.first_name = "Michael"
- # p1.save
- #
- # p2.destroy # Raises a ActiveRecord::StaleObjectError
- #
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
# or otherwise apply the business logic needed to resolve the conflict.
#
@@ -49,7 +39,6 @@ module ActiveRecord
self.lock_optimistically = true
alias_method_chain :update, :lock
- alias_method_chain :destroy, :lock
alias_method_chain :attributes_from_column_definition, :lock
class << self
@@ -111,29 +100,6 @@ module ActiveRecord
end
end
- def destroy_with_lock #:nodoc:
- return destroy_without_lock unless locking_enabled?
-
- unless new_record?
- lock_col = self.class.locking_column
- previous_value = send(lock_col).to_i
-
- arel_table = self.class.arel_table(self.class.table_name)
-
- affected_rows = arel_table.where(
- arel_table[self.class.primary_key].eq(quoted_id).and(
- arel_table[self.class.locking_column].eq(quote_value(previous_value))
- )
- ).delete
-
- unless affected_rows == 1
- raise ActiveRecord::StaleObjectError, "Attempted to delete a stale object"
- end
- end
-
- freeze
- end
-
module ClassMethods
DEFAULT_LOCKING_COLUMN = 'lock_version'
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index edcf547e01..ca3110a374 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -250,6 +250,8 @@ module ActiveRecord
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
end
}, __FILE__, __LINE__
+
+ add_autosave_association_callbacks(reflection)
else
raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?"
end
diff --git a/activerecord/lib/active_record/notifications.rb b/activerecord/lib/active_record/notifications.rb
index a5ce7ac524..562a5b91f4 100644
--- a/activerecord/lib/active_record/notifications.rb
+++ b/activerecord/lib/active_record/notifications.rb
@@ -1,5 +1,5 @@
require 'active_support/notifications'
-ActiveSupport::Notifications.subscribe("sql") do |event|
- ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration)
+ActiveSupport::Notifications.subscribe("sql") do |name, before, after, result, instrumenter_id, payload|
+ ActiveRecord::Base.connection.log_info(payload[:sql], name, after - before)
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 6bc56ecf15..5f0eec754f 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -110,19 +110,17 @@ module ActiveRecord
end
def respond_to?(method)
- if @relation.respond_to?(method) || Array.instance_methods.include?(method.to_s)
- true
- else
- super
- end
+ @relation.respond_to?(method) || Array.method_defined?(method) || super
end
private
def method_missing(method, *args, &block)
if @relation.respond_to?(method)
@relation.send(method, *args, &block)
- elsif Array.instance_methods.include?(method.to_s)
+ elsif Array.method_defined?(method)
to_a.send(method, *args, &block)
+ else
+ super
end
end
end
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 0365cb592f..e8a2a72735 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/integer/even_odd'
-
module ActiveRecord
# Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.