diff options
Diffstat (limited to 'activerecord/lib/active_record')
4 files changed, 42 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 18d4291599..18da28d480 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1604,6 +1604,21 @@ module ActiveRecord # where("default_category = ?", category.name) # } # + # === Extensions + # + # The +extension+ argument allows you to pass a block into a + # has_and_belongs_to_many association. This is useful for adding new + # finders, creators and other factory-type methods to be used as part of + # the association. + # + # Extension examples: + # has_and_belongs_to_many :contractors do + # def find_or_create_by_name(name) + # first_name, last_name = name.split(" ", 2) + # find_or_create_by(first_name: first_name, last_name: last_name) + # end + # end + # # === Options # # [:class_name] diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 01f126f1b3..2f02738f6d 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -54,7 +54,19 @@ module ActiveRecord end def changed_attributes - super.reverse_merge(attributes_changed_in_place).freeze + # This should only be set by methods which will call changed_attributes + # multiple times when it is known that the computed value cannot change. + if defined?(@cached_changed_attributes) + @cached_changed_attributes + else + super.reverse_merge(attributes_changed_in_place).freeze + end + end + + def changes + cache_changed_attributes do + super + end end private @@ -157,6 +169,13 @@ module ActiveRecord store_original_raw_attribute(attr) end end + + def cache_changed_attributes + @cached_changed_attributes = changed_attributes + yield + ensure + remove_instance_variable(:@cached_changed_attributes) + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 323da7b717..767b6b614a 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -281,9 +281,9 @@ module ActiveRecord def default_sequence_name(table_name, pk = nil) #:nodoc: result = serial_sequence(table_name, pk || 'id') return nil unless result - Utils.extract_schema_qualified_name(result) + Utils.extract_schema_qualified_name(result).to_s rescue ActiveRecord::StatementInvalid - PostgreSQL::Name.new(nil, "#{table_name}_#{pk || 'id'}_seq") + PostgreSQL::Name.new(nil, "#{table_name}_#{pk || 'id'}_seq").to_s end def serial_sequence(table, column) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index d22806fbdf..82b9c79533 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -151,7 +151,7 @@ module ActiveRecord end def find_by(*args) - return super if current_scope || args.length > 1 || reflect_on_all_aggregations.any? + return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any? hash = args.first @@ -177,6 +177,10 @@ module ActiveRecord end end + def find_by!(*args) + find_by(*args) or raise RecordNotFound + end + def initialize_generated_modules super |