我通过关系查看了Rails指南关于has_many的信息,但是他们在视图中的控制器中的has_many通过效果的文档很差。
模特:
class Project < ActiveRecord::Base
has_many :twitter_memberships
has_many :twitter_accounts, through: :twitter_memberships
end
class TwitterAccount < ActiveRecord::Base
has_many :twitter_memberships
has_many :projects, through: :twitter_memberships
end
class TwitterMembership < ActiveRecord::Base
belongs_to :project
belongs_to :twitter_account
end
路线:
resources :projects do
resources :twitter_accounts
end
问题是,当我使用创建方法时,会自动创建一个TwitterMembership对象,但是当我使用新方法然后保存方法< / strong>,TwitterMembership尚未创建。 Stackoverflow中的许多帖子都说 create = new&amp;保存但似乎它们不一样。
例如:
Project.first.twitter_accounts.create(name: "bar")
正在创建TwitterAccount和TwitterMembership:
SQL (0.5ms) INSERT INTO "twitter_accounts" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Thu, 20 Nov 2014 22:01:06 UTC +00:00], ["name", "test_record"], ["updated_at", Thu, 20 Nov 2014 22:01:06 UTC +00:00]]
SQL (0.3ms) INSERT INTO "twitter_memberships" ("created_at", "project_id", "twitter_account_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Thu, 20 Nov 2014 22:01:06 UTC +00:00], ["project_id", 1], ["twitter_account_id", 8], ["updated_at", Thu, 20 Nov 2014 22:01:06 UTC +00:00]]
但是当我在 controllers / twitter_accounts_controller 中使用 new&amp;创建 - 它没有创建TwitterMembership:
def new
@twitter_account = @project.twitter_accounts.new
end
def create
@twitter_account = @project.twitter_accounts.new(twitter_account_params)
@twitter_account.save
end
你能解释一下new-save和create之间的区别吗?如果我直接在我的控制器中使用创建方法,这样可以吗?
def create
@twitter_account = @project.twitter_accounts.create(twitter_account_params)
end
提前致谢。
修改。这是完整的控制器=&gt;
class TwitterAccountsController < ApplicationController
before_action :set_project
before_action :set_twitter_account, only: [:show, :edit, :update, :destroy]
def new
@twitter_account = @project.twitter_accounts.new
end
def create
@twitter_account = @project.twitter_accounts.new(twitter_account_params)
@twitter_account.save
end
private
def set_project
@project = Project.friendly.find(params[:project_id])
end
def set_twitter_account
@twitter_account = TwitterAccount.friendly.find(params[:id])
end
def twitter_account_params
params.require(:twitter_account).permit(:name, :account_id)
end
end
答案 0 :(得分:2)
您需要在模型上设置反向关系,以保证关联上的build
和new
能够始终如一地设置关系,外键和中间关联:
class Project < ActiveRecord::Base
has_many :twitter_memberships, inverse_of: :project
has_many :twitter_accounts, through: :twitter_memberships
end
class TwitterMembership < ActiveRecord::Base
belongs_to :project, inverse_of: :twitter_memberships
belongs_to :twitter_account, inverse_of: :twitter_memberships
end
class TwitterAccount < ActiveRecord::Base
has_many :twitter_memberships, inverse_of: :twitter_account
has_many :projects, through: :twitter_memberships
end
然后应该让这项工作
@twitter_account = Project.first.twitter_accounts.new(name: 'baz')
@twitter_account.save
瞧:
SQL (0.3ms) INSERT INTO "twitter_accounts" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", "2014-11-21 19:19:06.323072"], ["name", "baz"], ["updated_at", "2014-11-21 19:19:06.323072"]]
SQL (0.1ms) INSERT INTO "twitter_memberships" ("created_at", "project_id", "twitter_account_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", "2014-11-21 19:19:06.324779"], ["project_id", 1], ["twitter_account_id", 7], ["updated_at", "2014-11-21 19:19:06.324779"]]
此外,假设您在发生故障时处理了所有边缘情况,使用create
是完全可以接受的。例如:如果失败,您是否向最终用户显示错误?如果它不应该失败,你应该引发一个异常(见create!
)以生成某种通知,告知你失败。
简而言之,如果inverse_of
上没有has_many
设置,has_one
和belongs_to
Rails就无法完全理解将各种事物粘合在一起的中间模型链。 Rails在某些情况下(如create
)会采取“最佳猜测”,并可能使事情正确。 Rails指南并没有说明这一点,但the documentation on inverse_of说明了这一点。
在所有inverse_of
,has_many
和has_one
关系中设置belongs_to
已成为Rails习惯用语,应该这样做以确保Rails没有必要进行猜测