[英]Rails Has Many Through Relationship - Difference Between New-Save and Create
我檢查了有關has_many through關系的Rails指南,但是對於has_many through在視圖中的控制器中的效果,它們的文檔很差。
型號:
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
問題是,當我使用create方法時 ,會自動創建一個TwitterMembership對象,但是當我使用new方法然后再使用save方法時 ,不會創建TwitterMembership。 Stackoverflow中的許多帖子都說create = new&save,但似乎它們並不相同。
例如:
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]]
但是,當我使用new&create在controllers / twitter_accounts_controller中執行相同的操作時,它不是在創建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
您能解釋一下新保存和創建之間的區別嗎? 這樣直接在控制器中使用create方法可以嗎?
def create
@twitter_account = @project.twitter_accounts.create(twitter_account_params)
end
提前致謝。
編輯。 這是完整的控制器=>
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
您需要在模型上設置逆向關系,以確保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!
),以生成某種通知以通知您失敗。
簡而言之,如果沒有在has_many
, has_one
和belongs_to
上的inverse_of
設置,Rails不會完全理解將事物粘合在一起的中間模型鏈。 在某些情況下(例如create
),Rails會做出“最佳猜測”,並可能使事情變得正確。 Rails指南並不清楚,但是有關inverse_of的文檔對此進行了說明。
在所有has_many
, has_one
和belongs_to
關系上設置inverse_of
已成為Rails慣用語,應確保不要使用Rails進行猜測。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.