diff options
Diffstat (limited to 'activerecord/lib')
12 files changed, 65 insertions, 29 deletions
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 1759a41d93..d78717704c 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -34,7 +34,10 @@ module ActiveRecord::Associations::Builder method_name = "belongs_to_counter_cache_before_destroy_for_#{name}" mixin.redefine_method(method_name) do record = send(name) - record.class.decrement_counter(cache_column, record.id) unless record.nil? + + if record && !self.destroyed? + record.class.decrement_counter(cache_column, record.id) + end end model.before_destroy(method_name) diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 65e882867e..baddb9852f 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -43,7 +43,7 @@ module ActiveRecord # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items def ids_reader - if loaded? || options[:finder_sql] + if owner.new_record? || loaded? || options[:finder_sql] load_target.map do |record| record.send(reflection.association_primary_key) end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 059e6c77bc..5296cb7282 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -89,8 +89,7 @@ module ActiveRecord records.each { |r| r.destroy } update_counter(-records.length) unless inverse_updates_counter_cache? else - keys = records.map { |r| r[reflection.association_primary_key] } - scope = scoped.where(reflection.association_primary_key => keys) + scope = self.scoped.where(reflection.klass.primary_key => records) if method == :delete_all update_counter(-scope.delete_all) diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index cd366ac8b7..e3d8356f49 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -109,7 +109,7 @@ module ActiveRecord case associations when Symbol, String reflection = parent.reflections[associations.to_s.intern] or - raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" + raise ConfigurationError, "Association named '#{ associations }' was not found on #{parent.active_record.name}; perhaps you misspelled it?" unless join_association = find_join_association(reflection, parent) @reflections << reflection join_association = build_join_association(reflection, parent) diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb index 03963ab060..becf1a3f62 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -55,7 +55,12 @@ module ActiveRecord def find_parent_in(other_join_dependency) other_join_dependency.join_parts.detect do |join_part| - parent == join_part + case parent + when JoinBase + parent.active_record == join_part.active_record + else + parent == join_part + end end end diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index e1499fc3b0..3fc9d307bc 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -332,16 +332,16 @@ module ActiveRecord if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave) begin - records_to_destroy = [] + if autosave + records_to_destroy = records.select(&:marked_for_destruction?) + records_to_destroy.each { |record| association.proxy.destroy(record) } + records -= records_to_destroy + end records.each do |record| - next if record.destroyed? - saved = true - if autosave && record.marked_for_destruction? - records_to_destroy << record - elsif autosave != false && (@new_record_before_save || record.new_record?) + if autosave != false && (@new_record_before_save || record.new_record?) if autosave saved = association.insert_record(record, false) else @@ -353,19 +353,14 @@ module ActiveRecord raise ActiveRecord::Rollback unless saved end - - records_to_destroy.each do |record| - association.proxy.destroy(record) - end rescue records.each {|x| IdentityMap.remove(x) } if IdentityMap.enabled? raise end - end # reconstruct the scope now that we know the owner's id - association.send(:reset_scope) if association.respond_to?(:reset_scope) + association.reset_scope if association.respond_to?(:reset_scope) 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 524a7d30fc..c690b982a1 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -204,9 +204,11 @@ module ActiveRecord # Executes the SQL statement in the context of this connection. def execute(sql, name = nil) - # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been - # made since we established the connection - @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone + if @connection + # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been + # made since we established the connection + @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone + end super end diff --git a/activerecord/lib/active_record/explain_subscriber.rb b/activerecord/lib/active_record/explain_subscriber.rb index 859c8edfc5..1d861a57db 100644 --- a/activerecord/lib/active_record/explain_subscriber.rb +++ b/activerecord/lib/active_record/explain_subscriber.rb @@ -15,7 +15,7 @@ module ActiveRecord # On the other hand, we want to monitor the performance of our real database # queries, not the performance of the access to the query cache. IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE) - EXPLAINED_SQLS = /\A\s*(select|update|delete|insert)/i + EXPLAINED_SQLS = /\A\s*(select|update|delete|insert)\b/i def ignore_payload?(payload) payload[:exception] || IGNORED_PAYLOADS.include?(payload[:name]) || payload[:sql] !~ EXPLAINED_SQLS end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 13b7c6e214..4e39654e5b 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -30,6 +30,7 @@ module ActiveRecord ) rake_tasks do + require "active_record/base" load "active_record/railties/databases.rake" end @@ -38,9 +39,14 @@ module ActiveRecord # first time. Also, make it output to STDERR. console do |app| require "active_record/railties/console_sandbox" if app.sandbox? + require "active_record/base" ActiveRecord::Base.logger = Logger.new(STDERR) end + runner do |app| + require "active_record/base" + end + initializer "active_record.initialize_timezone" do ActiveSupport.on_load(:active_record) do self.time_zone_aware_attributes = true diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 1f9dbdc3d4..afab793a0c 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -179,14 +179,13 @@ module ActiveRecord def pluck(column_name) if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s) column_name = "#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}" - else - column_name = column_name.to_s end - relation = clone - relation.select_values = [column_name] - klass.connection.select_all(relation.arel).map! do |attributes| - klass.type_cast_attribute(attributes.keys.first, klass.initialize_attributes(attributes)) + result = klass.connection.exec_query(select(column_name).to_sql) + last_column = result.columns.last + + result.map do |attributes| + klass.type_cast_attribute(last_column, klass.initialize_attributes(attributes)) end end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 08cfe4f70d..cdf18f8080 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -254,6 +254,7 @@ module ActiveRecord values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) relation = relation.dup.select(values) + relation.uniq_value = nil id_rows = @klass.connection.select_all(relation.arel, 'SQL', relation.bind_values) ids_array = id_rows.map {|row| row[primary_key]} diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index b8e384c2f3..90f2ac3cde 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -27,7 +27,7 @@ module ActiveRecord merge_relation_method(merged_relation, method, value) if value.present? end - merged_relation.joins_values += r.joins_values + merge_joins(merged_relation, r) merged_wheres = @where_values + r.where_values @@ -146,6 +146,32 @@ module ActiveRecord private + def merge_joins(relation, other) + values = other.joins_values + return if values.blank? + + if other.klass == relation.klass + relation.joins_values += values + else + joins_dependency, rest = values.partition do |join| + case join + when Hash, Symbol, Array + true + else + false + end + end + + join_dependency = ActiveRecord::Associations::JoinDependency.new( + other.klass, + joins_dependency, + [] + ) + + relation.joins_values += join_dependency.join_associations + rest + end + end + def merge_relation_method(relation, method, value) relation.send(:"#{method}_values=", relation.send(:"#{method}_values") + value) end |