Rails 7 allows constructors on has_one :through associations
source link: https://blog.saeloun.com/2021/04/27/rails-7-allow-constructor-in-has-one-through
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 7 allows constructors on has_one :through associations
Apr 27, 2021 , by Mayank Khanna 1 minute readWhen we declare a belongs_to
association, the declaring class automatically
gains
build_association
and
create_association
methods.
For example, given the declaration:
class Book < ApplicationRecord
belongs_to :author
end
Each instance of the Book model will have build_author
and create_author
methods.
Now let’s consider the following models.
# app/models/supplier.rb
class Supplier < ApplicationRecord
has_one :account
has_one :account_history, through: :account
end
# app/models/account.rb
class Account < ApplicationRecord
belongs_to :supplier
has_one :account_history
end
# app/models/account_history.rb
class AccountHistory < ApplicationRecord
belongs_to :account
end
To create a supplier account, we can call create_account
on the Supplier object as shown below:
Supplier.first.create_account
# Supplier Load (0.5ms) SELECT "suppliers".* FROM "suppliers" ORDER BY "suppliers"."id" ASC LIMIT $1 [["LIMIT", 1]]
# Account Load (0.5ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."supplier_id" = $1 LIMIT $2
[["supplier_id", "6700d0ba-b8ed-4ff5-bb69-c57e7ea7f285"], ["LIMIT", 1]]
The direct association of has_one: :account
works as expected.
But when we try to create AccountHistory, we get the below error:
Supplier.first.create_account_history
# Supplier Load (0.5ms) SELECT "suppliers".* FROM "suppliers" ORDER BY "suppliers"."id" ASC LIMIT $1 [["LIMIT", 1]]
NoMethodError: undefined method `create_account_history' for #<Supplier:0x00007f949d6016c8>
As we can see, the create_account_history
method is missing when we created the has_one :through
relationship.
Before:
Before Rails 7,
to fix the above issue,
we can add a method create_account_history
to the Supplier
model.
class Supplier < ApplicationRecord
has_one :account
has_one :account_history, through: :account
def create_account_history
account = self.account
account.create_account_history
end
end
This change works as expected, but we would end up writing similar methods
for all our has_one :through
associations.
After:
To resolve the above issue,
Rails 7
allows
build_association
and create_association
on has_one :through associations.
AccountHistory can be created via Supplier object as shown below.
Supplier.first.create_account_history
# AccountHistory Create (1.3ms) INSERT INTO "account_histories" ("account_id", "user_id") VALUES ($1, $2) RETURNING "id" [["account_id", "5d671a08-1513-442a-8cfa-ac00e128d423"], ["user_id", "24571aff-3456-442a-8cfa-aerte128d423"], ["organization_user_id""6700d0ba-b8ed-4ff5-bb69-c57e7ea7f285"], ["created_at", "2021-04-09 06:26:59.002535"], ["updated_at", "2021-04-09 06:26:59.002535"]]
Similarly, build_account_history
will work and, it will not throw a NoMethodError
exception.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK