From b29c01ea8914422c6f7e0bb5c65d3b8610dc54d1 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 24 Jan 2005 11:39:23 +0000 Subject: Added that has_and_belongs_to_many associations with additional attributes also can be created between unsaved objects and only committed to the database when Base#save is called on the associator #524 [Eric Anderson] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@484 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../has_and_belongs_to_many_association.rb | 37 ++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'activerecord/lib/active_record/associations') diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index 83b87547ee..77d2fb9cde 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -81,8 +81,8 @@ module ActiveRecord def push_with_attributes(record, join_attributes = {}) raise_on_type_mismatch(record) - insert_record_with_join_attributes(record, join_attributes) - join_attributes.each { |key, value| record.send(:write_attribute, key, value) } + join_attributes.each { |key, value| record[key.to_s] = value } + insert_record(record) unless @owner.new_record? @target << record self end @@ -105,22 +105,33 @@ module ActiveRecord def insert_record(record) return false unless record.save + if @options[:insert_sql] @owner.connection.execute(interpolate_sql(@options[:insert_sql], record)) else - sql = "INSERT INTO #{@join_table} (#{@association_class_primary_key_name}, #{@association_foreign_key}) " + - "VALUES (#{@owner.quoted_id},#{record.quoted_id})" + columns = @owner.connection.columns(@join_table, "#{@join_table} Columns") + + attributes = columns.inject({}) do |attributes, column| + case column.name + when @association_class_primary_key_name + attributes[column.name] = @owner.quoted_id + when @association_foreign_key + attributes[column.name] = record.quoted_id + else + value = record[column.name] + attributes[column.name] = value unless value.nil? + end + attributes + end + + sql = + "INSERT INTO #{@join_table} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " + + "VALUES (#{attributes.values.collect { |value| @owner.send(:quote, value) }.join(', ')})" + @owner.connection.execute(sql) end - true - end - - def insert_record_with_join_attributes(record, join_attributes) - attributes = { @association_class_primary_key_name => @owner.id, @association_foreign_key => record.id }.update(join_attributes) - sql = - "INSERT INTO #{@join_table} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " + - "VALUES (#{attributes.values.collect { |value| @owner.send(:quote, value) }.join(', ')})" - @owner.connection.execute(sql) + + return true end def delete_records(records) -- cgit v1.2.3