Skip to content

Commit

Permalink
Infer foerign_key when inverse_of is present (#47797)
Browse files Browse the repository at this point in the history
* Infer `foerign_key` when `inverse_of` is present

Automatically infer `foreign_key` on `has_one` and `has_many` associations when `inverse_of` is present.

When inverse of is present, rails has all the info it needs to figure out what the foreign_key on the associated model should be.  I can't imagine this breaking anything

* Update test models to remove redundant foreign_keys

* add changelog entry

* fix changelog grammar

Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
  • Loading branch information
Tiedye and rafaelfranca committed Mar 30, 2023
1 parent aa3787c commit 15369fd
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 8 deletions.
16 changes: 16 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,19 @@
* Infer `foerign_key` when `inverse_of` is present on `has_one` and `has_many` associations.

```ruby
has_many :citations, foreign_key: "book1_id", inverse_of: :book
```

can be simplified to

```ruby
has_many :citations, inverse_of: :book
```

and the foreign_key will be read from the corresponding `belongs_to` association.

*Daniel Whitney*

* Limit max length of auto generated index names

Auto generated index names are now limited to 62 bytes, which fits within
Expand Down
2 changes: 2 additions & 0 deletions activerecord/lib/active_record/reflection.rb
Expand Up @@ -731,6 +731,8 @@ def derive_foreign_key
"#{name}_id"
elsif options[:as]
"#{options[:as]}_id"
elsif options[:inverse_of]
inverse_of.foreign_key
else
active_record.model_name.to_s.foreign_key
end
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/book.rb
Expand Up @@ -4,7 +4,7 @@ class Book < ActiveRecord::Base
belongs_to :author
belongs_to :format_record, polymorphic: true

has_many :citations, foreign_key: "book1_id", inverse_of: :book
has_many :citations, inverse_of: :book
has_many :references, -> { distinct }, through: :citations, source: :reference_of

has_many :subscriptions
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/comment.rb
Expand Up @@ -23,7 +23,7 @@ class Comment < ActiveRecord::Base
belongs_to :first_post, foreign_key: :post_id
belongs_to :special_post_with_default_scope, foreign_key: :post_id

has_many :children, class_name: "Comment", foreign_key: :parent_id, inverse_of: :parent
has_many :children, class_name: "Comment", inverse_of: :parent
belongs_to :parent, class_name: "Comment", counter_cache: :children_count, inverse_of: :children

alias_attribute :entry, :post
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/company.rb
Expand Up @@ -58,7 +58,7 @@ class Firm < Company
has_many :unsorted_clients, class_name: "Client"
has_many :unsorted_clients_with_symbol, class_name: :Client
has_many :clients_sorted_desc, -> { order "id DESC" }, class_name: "Client"
has_many :clients_of_firm, -> { order "id" }, foreign_key: "client_of", class_name: "Client", inverse_of: :firm
has_many :clients_of_firm, -> { order "id" }, class_name: "Client", inverse_of: :firm
has_many :clients_ordered_by_name, -> { order "name" }, class_name: "Client"
has_many :unvalidated_clients_of_firm, foreign_key: "client_of", class_name: "Client", validate: false
has_many :dependent_clients_of_firm, -> { order "id" }, foreign_key: "client_of", class_name: "Client", dependent: :destroy
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/human.rb
Expand Up @@ -4,7 +4,7 @@ class Human < ActiveRecord::Base
self.table_name = "humans"

has_one :face, inverse_of: :human
has_one :autosave_face, class_name: "Face", autosave: true, foreign_key: :human_id, inverse_of: :autosave_human
has_one :autosave_face, class_name: "Face", autosave: true, inverse_of: :autosave_human
has_one :polymorphic_face, class_name: "Face", as: :polymorphic_human, inverse_of: :polymorphic_human
has_one :polymorphic_face_without_inverse, class_name: "Face", as: :poly_human_without_inverse
has_many :interests, inverse_of: :human
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/pirate.rb
Expand Up @@ -98,7 +98,7 @@ class DestructivePirate < Pirate

class FamousPirate < ActiveRecord::Base
self.table_name = "pirates"
has_many :famous_ships, inverse_of: :famous_pirate, foreign_key: :pirate_id
has_many :famous_ships, inverse_of: :famous_pirate
validates_presence_of :catchphrase, on: :conference
end

Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/ship.rb
Expand Up @@ -24,7 +24,7 @@ def cancel_save_callback_method

class ShipWithoutNestedAttributes < ActiveRecord::Base
self.table_name = "ships"
has_many :prisoners, inverse_of: :ship, foreign_key: :ship_id
has_many :prisoners, inverse_of: :ship
has_many :parts, class_name: "ShipPart", foreign_key: :ship_id

validates :name, presence: true, if: -> { true }
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/topic.rb
Expand Up @@ -46,7 +46,7 @@ def two
end
end

has_many :replies, dependent: :destroy, foreign_key: "parent_id", autosave: true, inverse_of: :topic
has_many :replies, dependent: :destroy, autosave: true, inverse_of: :topic
has_many :approved_replies, -> { approved }, class_name: "Reply", foreign_key: "parent_id", counter_cache: "replies_count"
has_many :open_replies, -> { open }, class_name: "Reply", foreign_key: "parent_id"

Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/zine.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true

class Zine < ActiveRecord::Base
has_many :interests, inverse_of: :zine, foreign_key: "zine_id"
has_many :interests, inverse_of: :zine
end

0 comments on commit 15369fd

Please sign in to comment.