如何在初始化另一个模型后正确地进行回调以创建模型?
How to properly make a callback to create a model, after initialize of another model?
首先,我可能对我正在尝试做的事情使用了错误的回调
and/or 可能有更好的“Rails 方式”来完成此任务。如果是这样,我洗耳恭听。
我一直在引用 api.rubyonrails.org/v7.0.1/classes/ActiveRecord/Callbacks/ClassMethods
和
guides.rubyonrails.org/active_record_callbacks.html#creating-an-object
我需要实施:
“用户注册创建一个与所有者关联的帐户”
(最终,用户将 belong_to 个帐户,帐户将 has_many 个用户)
数据库架构中的帐户有 name:string 和 owner_id:integer
目前,我无法访问新创建的用户,也没有创建帐户。我想我已经很接近了。
当前 models/user.rb
:
class User < ApplicationRecord
after_save :create_account
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
private
def create_account
Account.create(owner_id: user.id, name: "#{user.name}'s Account")
redirect_to root_path
end
end
输出到堆栈跟踪:
Started POST "/users" for ::1 at 2022-02-04 23:39:40 -0600
Processing by RegistrationsController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"name"=>"tester", "phonenumber"=>"1234567890", "email"=>"test@test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
TRANSACTION (0.2ms) BEGIN
User Exists? (1.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = LIMIT [["email", "test@test.com"], ["LIMIT", 1]]
User Create (0.6ms) INSERT INTO "users" ("email", "encrypted_password", "reset_password_token", "reset_password_sent_at", "remember_created_at", "created_at", "updated_at", "name", "phonenumber") VALUES (, , , , , , , , ) RETURNING "id" [["email", "test@test.com"], ["encrypted_password", "[FILTERED]"], ["reset_password_token", "[FILTERED]"], ["reset_password_sent_at", "[FILTERED]"], ["remember_created_at", nil], ["created_at", "2022-02-05 05:39:40.493526"], ["updated_at", "2022-02-05 05:39:40.493526"], ["name", "tester"], ["phonenumber", "1234567890"]]
TRANSACTION (0.2ms) ROLLBACK
Completed 500 Internal Server Error in 298ms (ActiveRecord: 2.1ms | Allocations: 9928)
NameError (undefined local variable or method `user' for #<User id: nil, email: "test@test.com", created_at: "2022-02-05 05:39:40.493526000 +0000", updated_at: "2022-02-05 05:39:40.493526000 +0000", name: "tester", phonenumber: "1234567890">
Did you mean? super):
app/models/user.rb:12:in `create_account'
正如 prasannaboga 已经在他的评论中写的那样。像这样的回调在实例上下文中是 运行。这意味着您不需要首先调用特定的 user
,因为当前对象已经是该用户。
此外,在模型的上下文中,redirect_to
调用没有任何意义。模型对请求和响应一无所知。 redirect_to
是一个控制器方法,您需要将它添加到您的控制器中。
以下回调方法应该有效:
def create_account
Account.create(owner_id: id, name: "#{name}'s Account")
结束
我想知道您为什么决定不向您的 User
模型添加 has_one :account
或 has_many :accounts
关联?通过这样做,您可以进一步简化方法,因为 Rails 会自动处理 id
的设置,就像这样
build_account(name: "#{name}'s Account") # when `has_one` or
accounts.build(name: "#{name}'s Account") # when `has_many`
首先,我可能对我正在尝试做的事情使用了错误的回调
and/or 可能有更好的“Rails 方式”来完成此任务。如果是这样,我洗耳恭听。
我一直在引用 api.rubyonrails.org/v7.0.1/classes/ActiveRecord/Callbacks/ClassMethods
和
guides.rubyonrails.org/active_record_callbacks.html#creating-an-object
我需要实施:
“用户注册创建一个与所有者关联的帐户”
(最终,用户将 belong_to 个帐户,帐户将 has_many 个用户)
数据库架构中的帐户有 name:string 和 owner_id:integer
目前,我无法访问新创建的用户,也没有创建帐户。我想我已经很接近了。
当前 models/user.rb
:
class User < ApplicationRecord
after_save :create_account
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
private
def create_account
Account.create(owner_id: user.id, name: "#{user.name}'s Account")
redirect_to root_path
end
end
输出到堆栈跟踪:
Started POST "/users" for ::1 at 2022-02-04 23:39:40 -0600
Processing by RegistrationsController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"name"=>"tester", "phonenumber"=>"1234567890", "email"=>"test@test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
TRANSACTION (0.2ms) BEGIN
User Exists? (1.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = LIMIT [["email", "test@test.com"], ["LIMIT", 1]]
User Create (0.6ms) INSERT INTO "users" ("email", "encrypted_password", "reset_password_token", "reset_password_sent_at", "remember_created_at", "created_at", "updated_at", "name", "phonenumber") VALUES (, , , , , , , , ) RETURNING "id" [["email", "test@test.com"], ["encrypted_password", "[FILTERED]"], ["reset_password_token", "[FILTERED]"], ["reset_password_sent_at", "[FILTERED]"], ["remember_created_at", nil], ["created_at", "2022-02-05 05:39:40.493526"], ["updated_at", "2022-02-05 05:39:40.493526"], ["name", "tester"], ["phonenumber", "1234567890"]]
TRANSACTION (0.2ms) ROLLBACK
Completed 500 Internal Server Error in 298ms (ActiveRecord: 2.1ms | Allocations: 9928)
NameError (undefined local variable or method `user' for #<User id: nil, email: "test@test.com", created_at: "2022-02-05 05:39:40.493526000 +0000", updated_at: "2022-02-05 05:39:40.493526000 +0000", name: "tester", phonenumber: "1234567890">
Did you mean? super):
app/models/user.rb:12:in `create_account'
正如 prasannaboga 已经在他的评论中写的那样。像这样的回调在实例上下文中是 运行。这意味着您不需要首先调用特定的 user
,因为当前对象已经是该用户。
此外,在模型的上下文中,redirect_to
调用没有任何意义。模型对请求和响应一无所知。 redirect_to
是一个控制器方法,您需要将它添加到您的控制器中。
以下回调方法应该有效:
def create_account Account.create(owner_id: id, name: "#{name}'s Account") 结束
我想知道您为什么决定不向您的 User
模型添加 has_one :account
或 has_many :accounts
关联?通过这样做,您可以进一步简化方法,因为 Rails 会自动处理 id
的设置,就像这样
build_account(name: "#{name}'s Account") # when `has_one` or
accounts.build(name: "#{name}'s Account") # when `has_many`