Merge pull request #47230 from Shopify/composite-foreign-key-assoc-assignment
Support composite foreign key association assignments
This commit is contained in:
commit
5defeececb
@ -119,10 +119,13 @@ def require_counter_update?
|
||||
end
|
||||
|
||||
def replace_keys(record, force: false)
|
||||
target_key = record ? record._read_attribute(primary_key(record.class)) : nil
|
||||
target_key_values = record ? Array(primary_key(record.class)).map { |key| record._read_attribute(key) } : []
|
||||
reflection_fk = Array(reflection.foreign_key)
|
||||
|
||||
if force || owner._read_attribute(reflection.foreign_key) != target_key
|
||||
owner[reflection.foreign_key] = target_key
|
||||
if force || reflection_fk.map { |fk| owner._read_attribute(fk) } != target_key_values
|
||||
reflection_fk.zip(target_key_values).each do |key, value|
|
||||
owner[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -22,8 +22,15 @@ def nullified_owner_attributes
|
||||
def set_owner_attributes(record)
|
||||
return if options[:through]
|
||||
|
||||
key = owner._read_attribute(reflection.join_foreign_key)
|
||||
record._write_attribute(reflection.join_primary_key, key)
|
||||
primary_key_attribute_names = Array(reflection.join_primary_key)
|
||||
foreign_key_attribute_names = Array(reflection.join_foreign_key)
|
||||
|
||||
primary_key_foreign_key_pairs = primary_key_attribute_names.zip(foreign_key_attribute_names)
|
||||
|
||||
primary_key_foreign_key_pairs.each do |primary_key, foreign_key|
|
||||
value = owner._read_attribute(foreign_key)
|
||||
record._write_attribute(primary_key, value)
|
||||
end
|
||||
|
||||
if reflection.type
|
||||
record._write_attribute(reflection.type, owner.class.polymorphic_name)
|
||||
|
@ -505,8 +505,14 @@ def save_belongs_to_association(reflection)
|
||||
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
||||
|
||||
if association.updated?
|
||||
association_id = record.public_send(reflection.options[:primary_key] || :id)
|
||||
self[reflection.foreign_key] = association_id unless self[reflection.foreign_key] == association_id
|
||||
primary_key = Array(reflection.options[:primary_key] || record.class.query_constraints_list)
|
||||
foreign_key = Array(reflection.foreign_key)
|
||||
|
||||
primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
|
||||
primary_key_foreign_key_pairs.each do |primary_key, foreign_key|
|
||||
association_id = record.public_send(primary_key)
|
||||
self[foreign_key] = association_id unless self[foreign_key] == association_id
|
||||
end
|
||||
association.loaded!
|
||||
end
|
||||
|
||||
|
@ -165,6 +165,72 @@ def test_model_with_composite_query_constraints_has_many_association_sql
|
||||
assert_match(/#{Regexp.escape(Sharded::Comment.connection.quote_table_name("sharded_comments.blog_post_id"))} =/, sql)
|
||||
assert_match(/#{Regexp.escape(Sharded::Comment.connection.quote_table_name("sharded_comments.blog_id"))} =/, sql)
|
||||
end
|
||||
|
||||
def test_append_composite_foreign_key_has_many_association
|
||||
blog_post = sharded_blog_posts(:great_post_blog_one)
|
||||
comment = Sharded::Comment.new(body: "Great post! :clap:")
|
||||
comment.save
|
||||
blog_post.comments << comment
|
||||
|
||||
assert_includes(blog_post.comments, comment)
|
||||
assert_equal(blog_post.id, comment.blog_post_id)
|
||||
assert_equal(blog_post.blog_id, comment.blog_id)
|
||||
end
|
||||
|
||||
def test_assign_persisted_composite_foreign_key_belongs_to_association
|
||||
comment = sharded_comments(:great_comment_blog_post_one)
|
||||
another_blog = sharded_blogs(:sharded_blog_two)
|
||||
assert_not_equal(comment.blog_id, another_blog.id)
|
||||
|
||||
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
||||
blog_post.save
|
||||
comment.blog_post = blog_post
|
||||
|
||||
assert_equal(blog_post, comment.blog_post)
|
||||
assert_equal(comment.blog_id, blog_post.blog_id)
|
||||
assert_equal(another_blog.id, comment.blog_id)
|
||||
assert_equal(comment.blog_post_id, blog_post.id)
|
||||
end
|
||||
|
||||
def test_assign_composite_foreign_key_belongs_to_association
|
||||
comment = sharded_comments(:great_comment_blog_post_one)
|
||||
another_blog = sharded_blogs(:sharded_blog_two)
|
||||
assert_not_equal(comment.blog_id, another_blog.id)
|
||||
|
||||
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
||||
comment.blog_post = blog_post
|
||||
|
||||
assert_equal(blog_post, comment.blog_post)
|
||||
assert_equal(comment.blog_id, blog_post.blog_id)
|
||||
assert_equal(another_blog.id, comment.blog_id)
|
||||
end
|
||||
|
||||
def test_append_composite_foreign_key_has_many_association_with_autosave
|
||||
blog_post = sharded_blog_posts(:great_post_blog_one)
|
||||
comment = Sharded::Comment.new(body: "Great post! :clap:")
|
||||
blog_post.comments << comment
|
||||
|
||||
assert_predicate(comment, :persisted?)
|
||||
assert_includes(blog_post.comments, comment)
|
||||
assert_equal(blog_post.id, comment.blog_post_id)
|
||||
assert_equal(blog_post.blog_id, comment.blog_id)
|
||||
end
|
||||
|
||||
def test_assign_composite_foreign_key_belongs_to_association_with_autosave
|
||||
comment = sharded_comments(:great_comment_blog_post_one)
|
||||
another_blog = sharded_blogs(:sharded_blog_two)
|
||||
assert_not_equal(comment.blog_id, another_blog.id)
|
||||
|
||||
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
||||
comment.blog_post = blog_post
|
||||
comment.save
|
||||
|
||||
assert_predicate(blog_post, :persisted?)
|
||||
assert_equal(blog_post, comment.blog_post)
|
||||
assert_equal(comment.blog_id, blog_post.blog_id)
|
||||
assert_equal(another_blog.id, comment.blog_id)
|
||||
assert_equal(comment.blog_post_id, blog_post.id)
|
||||
end
|
||||
end
|
||||
|
||||
class AssociationProxyTest < ActiveRecord::TestCase
|
||||
|
Loading…
Reference in New Issue
Block a user