Skip to content

Commit

Permalink
Fix replacing foreign key for a CPK association by id attribute
Browse files Browse the repository at this point in the history
Given a model associated with a composite primary key by `id` attribute,
for example:
```ruby
Order.primary_key = [:shop_id, :id]
OrderAgreement.primary_key = :id

OrderAgreement.belongs_to :order, primary_key: :id
```

Assigning `order` to an `OrderAgreement` object will replace the
`order_id` foreign key:

```ruby
order = Order.last # => #<Order id: 1, shop_id: 2>

order_agreement = OrderAgreement.new(order: order).save
order_agreement.order_id # => 1
```
  • Loading branch information
nvasilevski committed Apr 12, 2023
1 parent 3d4dd9f commit c0da60f
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
6 changes: 3 additions & 3 deletions activerecord/lib/active_record/autosave_association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,12 @@ def save_belongs_to_association(reflection)
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)

if association.updated?
primary_key = Array(compute_primary_key(reflection, record))
primary_key = Array(compute_primary_key(reflection, record)).map(&:to_s)
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)
association_id = record._read_attribute(primary_key)
self[foreign_key] = association_id unless self[foreign_key] == association_id
end
association.loaded!
Expand All @@ -527,7 +527,7 @@ def compute_primary_key(reflection, record)
elsif reflection.options[:query_constraints] && (query_constraints = record.class.query_constraints_list)
query_constraints
else
:id
record.class.primary_key
end
end

Expand Down
16 changes: 16 additions & 0 deletions activerecord/test/cases/associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,22 @@ def test_assign_composite_foreign_key_belongs_to_association
assert_equal(another_blog.id, comment.blog_id)
end


def test_assign_belongs_to_cpk_model_by_id_attribute
order = cpk_orders(:cpk_groceries_order_1)
agreement = Cpk::OrderAgreement.new(signature: "signed")

agreement.order = order
agreement.save

assert_not_nil(agreement.reload.order)
assert_not_nil(agreement.order_id)

assert_equal(order, agreement.order)
_shop_id, order_id = order.id
assert_equal(order_id, agreement.order_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:")
Expand Down

0 comments on commit c0da60f

Please sign in to comment.