-
Notifications
You must be signed in to change notification settings - Fork 617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rails 71 composite pks #837
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -941,7 +941,7 @@ def load_association_ids(model) | |
association = association.target | ||
next if association.blank? || model.public_send(column_name).present? | ||
|
||
association_primary_key = Array(association_reflection.association_primary_key)[column_index] | ||
association_primary_key = Array(association_reflection.association_primary_key.tr("[]:", "").split(", "))[column_index] | ||
model.public_send("#{column_name}=", association.send(association_primary_key)) | ||
end | ||
end | ||
|
@@ -996,7 +996,10 @@ def find_associated_objects_for_import(associated_objects_by_class, model) | |
|
||
changed_objects = association.select { |a| a.new_record? || a.changed? } | ||
changed_objects.each do |child| | ||
child.public_send("#{association_reflection.foreign_key}=", model.id) | ||
Array(association_reflection.inverse_of&.foreign_key || association_reflection.foreign_key).each_with_index do |column, index| | ||
child.public_send("#{column}=", Array(model.id)[index]) | ||
end | ||
|
||
Comment on lines
+999
to
+1002
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another note for the reviewers. Let's now consider we want to recursively import the model CompositeBook and its children CompositeChapter. Here is the has_many relation on CompositeBook, mentioning the names of the columns id and author_id. These are the PK columns in the composite_books table. As we are setting the ids in the children, we need the columns as they are called in the children table (composite_chapters), which is here. So we need the inverse relation (the belongs_to in CompositeChapter), which has the names composite_book_id and author_id. In order not to break things, I kept the original association_reflection.foreign_key as a fallback. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good 👍 If an association doesn't explicitly state the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jkowens I tried it out, and it still works without the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's awesome 😄 |
||
# For polymorphic associations | ||
association_name = if model.class.respond_to?(:polymorphic_name) | ||
model.class.polymorphic_name | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
class Author < ActiveRecord::Base | ||
if ENV['AR_VERSION'].to_f >= 7.1 | ||
has_many :composite_books, query_constraints: [:id, :author_id], inverse_of: :author | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
class CompositeBook < ActiveRecord::Base | ||
self.primary_key = %i[id author_id] | ||
belongs_to :author | ||
if ENV['AR_VERSION'].to_f <= 7.0 | ||
unless ENV["SKIP_COMPOSITE_PK"] | ||
has_many :composite_chapters, inverse_of: :composite_book, | ||
foreign_key: [:id, :author_id] | ||
end | ||
else | ||
has_many :composite_chapters, inverse_of: :composite_book, | ||
query_constraints: [:id, :author_id] | ||
end | ||
|
||
def self.sequence_name | ||
"composite_book_id_seq" | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# frozen_string_literal: true | ||
|
||
class CompositeChapter < ActiveRecord::Base | ||
if ENV['AR_VERSION'].to_f >= 7.1 | ||
belongs_to :composite_book, inverse_of: :composite_chapters, | ||
query_constraints: [:composite_book_id, :author_id] | ||
end | ||
validates :title, presence: true | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
class Tag < ActiveRecord::Base | ||
self.primary_keys = :tag_id, :publisher_id unless ENV["SKIP_COMPOSITE_PK"] | ||
if ENV['AR_VERSION'].to_f <= 7.0 | ||
self.primary_keys = :tag_id, :publisher_id unless ENV["SKIP_COMPOSITE_PK"] | ||
else | ||
self.primary_key = [:tag_id, :publisher_id] unless ENV["SKIP_COMPOSITE_PK"] | ||
end | ||
self.primary_key = [:tag_id, :publisher_id] unless ENV["SKIP_COMPOSITE_PK"] | ||
has_many :books, inverse_of: :tag | ||
has_many :tag_aliases, inverse_of: :tag | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without a composite PK, the association_reflection.association_primary_key has a value of the format "id", whereas with a composite PK in ActiveRecord 7.1 the value is of the format "[:id, :account_id]" (again a String). The .tr loses the [, :, ] characters, so that the .split(", ") will give us an array of the two colums: ["id", "account_id"]