Skip to content

Commit

Permalink
Add support for nullifying CPK has_one associations
Browse files Browse the repository at this point in the history
Composite primary key records need to conditionally unset multiple
column attributes from the associated record in order to properly
support dependent: nullify.
  • Loading branch information
gmcgibbon committed Jun 21, 2023
1 parent 7dd27be commit 622485a
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 1 deletion.
Expand Up @@ -121,7 +121,9 @@ def remove_target!(method)
end

def nullify_owner_attributes(record)
record[reflection.foreign_key] = nil
Array(reflection.foreign_key).each do |foreign_key_column|
record[foreign_key_column] = nil unless foreign_key_column.in?(Array(record.class.primary_key))
end
end

def transaction_if(value, &block)
Expand Down
22 changes: 22 additions & 0 deletions activerecord/test/cases/associations/has_one_associations_test.rb
Expand Up @@ -145,6 +145,28 @@ def test_nullification_on_destroyed_association
assert_not_predicate developer, :persisted?
end

def test_nullification_on_cpk_association
book = Cpk::Book.create!(author_id: 1, number: 2)
other_book = Cpk::Book.create!(author_id: 3, number: 4)
order = Cpk::OrderWithNullifiedBook.create!(book: book)

order.book = other_book

assert_nil book.order_id
assert_nil book.shop_id
end

def test_nullification_on_cpk_association_with_pk_column
chapter = Cpk::Chapter.create!(author_id: 1, number: 2)
other_chapter = Cpk::Chapter.create!(author_id: 1, number: 4)
book = Cpk::NullifiedBook.create!(chapter: chapter, number: 1, author_id: 1)

book.chapter = other_chapter

assert_nil chapter.book_number
assert_not_nil chapter.author_id
end

def test_natural_assignment_to_nil_after_destroy
firm = companies(:rails_core)
old_account_id = firm.account.id
Expand Down
1 change: 1 addition & 0 deletions activerecord/test/models/cpk.rb
Expand Up @@ -7,3 +7,4 @@
require_relative "cpk/order_agreement"
require_relative "cpk/order_tag"
require_relative "cpk/tag"
require_relative "cpk/chapter"
6 changes: 6 additions & 0 deletions activerecord/test/models/cpk/book.rb
Expand Up @@ -6,6 +6,8 @@ class Book < ActiveRecord::Base

belongs_to :order, autosave: true, query_constraints: [:shop_id, :order_id]
belongs_to :author, class_name: "Cpk::Author"

has_many :chapters, query_constraints: [:author_id, :book_number]
end

class BestSeller < Book
Expand All @@ -14,4 +16,8 @@ class BestSeller < Book
class BrokenBook < Book
belongs_to :order
end

class NullifiedBook < Book
has_one :chapter, query_constraints: [:author_id, :book_number], dependent: :nullify
end
end
12 changes: 12 additions & 0 deletions activerecord/test/models/cpk/chapter.rb
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Cpk
class Chapter < ActiveRecord::Base
self.table_name = :cpk_chapters
# explicit definition is to allow schema definition to be simplified
# to be shared between different databases
self.primary_key = [:author_id, :number]

belongs_to :book, query_constraints: [:author_id, :book_number]
end
end
4 changes: 4 additions & 0 deletions activerecord/test/models/cpk/order.rb
Expand Up @@ -20,4 +20,8 @@ class BrokenOrder < Order
class OrderWithPrimaryKeyAssociatedBook < Order
has_one :book, primary_key: :id, foreign_key: :order_id
end

class OrderWithNullifiedBook < Order
has_one :book, query_constraints: [:shop_id, :order_id], dependent: :nullify
end
end
7 changes: 7 additions & 0 deletions activerecord/test/schema/schema.rb
Expand Up @@ -249,6 +249,13 @@
t.integer :shop_id
end

create_table :cpk_chapters, primary_key: [:author_id, :number], force: true do |t|
t.integer :author_id
t.integer :number
t.integer :book_number
t.string :title
end

create_table :cpk_authors, force: true do |t|
t.string :name
end
Expand Down

0 comments on commit 622485a

Please sign in to comment.