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 ++++++++++++++-------- activerecord/lib/active_record/base.rb | 12 ++++--- 2 files changed, 31 insertions(+), 18 deletions(-) (limited to 'activerecord/lib') 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) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ede60e3f6d..55fe29c8f5 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1115,11 +1115,13 @@ module ActiveRecord #:nodoc: # an SQL statement. def attributes_with_quotes(include_primary_key = true) columns_hash = self.class.columns_hash + attrs_quoted = @attributes.inject({}) do |attrs_quoted, pair| attrs_quoted[pair.first] = quote(pair.last, columns_hash[pair.first]) unless !include_primary_key && pair.first == self.class.primary_key attrs_quoted end - attrs_quoted.delete_if { | key, value | !self.class.columns_hash.keys.include?(key) } + + attrs_quoted.delete_if { |key, value| !self.class.columns_hash.keys.include?(key) } end # Quote strings appropriately for SQL statements. @@ -1178,7 +1180,7 @@ module ActiveRecord #:nodoc: unless value.empty? attributes[attribute_name] << - [find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value)] + [ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ] end end @@ -1203,10 +1205,10 @@ module ActiveRecord #:nodoc: end def quote_columns(column_quoter, hash) - hash.inject({}) {|list, pair| + hash.inject({}) do |list, pair| list[column_quoter.quote_column_name(pair.first)] = pair.last list - } + end end def quoted_comma_pair_list(column_quoter, hash) @@ -1231,4 +1233,4 @@ module ActiveRecord #:nodoc: string[0..3] == "--- " end end -end +end \ No newline at end of file -- cgit v1.2.3