[英]has_and_belongs_to_many or polymorphic has_many :through?
[英]Active Record Associations: has_and_belongs_to_many, has_many :through or polymorphic association?
我正在使用的Ruby on Rails應用允許users
創建和與其他users
共享agendas
。
此外,我們必須能夠:
user
的agendas
列表 agenda
關聯的users
列表 role
,然后在上面提到的列表中顯示該用戶的角色 我打算在user
和agenda
模型之間建立has_and_belongs_to_many
關聯,如下所示:
class User < ActiveRecord::Base
has_and_belongs_to_many :agendas
end
class Agenda < ActiveRecord::Base
has_and_belongs_to_many :users
end
但是后來我想知道這是否會讓我在給定用戶的給定議程頁面上獲得並顯示@user.agenda.user.role
roles
列表。
而且我認為我可能應該使用has_many :through
關聯,例如:
class User < ActiveRecord::Base
has_many :roles
has_many :agendas, through: :roles
end
class Role < ActiveRecord::Base
belongs_to :user
belongs_to :agenda
end
class Agenda < ActiveRecord::Base
has_many :roles
has_many :users, through: :roles
end
盡管我對一個user
具有多個roles
(每個agenda
一個)的想法很滿意,但是我不確定一個agenda
具有多個roles
(每個user
?)的想法。
最后,讓我感到困惑的是,我閱讀了有關多態關聯的文章,並認為它也可能是一個可行的解決方案,例如,如果這樣做,例如:
class Role < ActiveRecord::Base
belongs_to :definition, polymorphic: true
end
class User < ActiveRecord::Base
has_many :roles, as: :definition
end
class Agenda < ActiveRecord::Base
has_many :roles, as: :definition
end
以上任何解決方案聽起來都適合這種情況嗎?
更新 :做一些研究,我偶然發現了這篇文章(從2012年開始),它解釋說has_many :through
比has_and_belongs_to_many
是一個“更智能”的選擇。 就我而言,我仍然不確定agenda
是否會roles
許多roles
。
更新2 :正如@engineersmnkyn的注釋中所建議的那樣,解決此問題的方法是使用兩個聯接表。 我嘗試實現以下代碼:
class User < ActiveRecord::Base
has_many :agendas, through: :jointable
end
class Agenda < ActiveRecord::Base
end
class Role < ActiveRecord::Base
end
class Jointable < ActiveRecord::Base
belongs_to :user
belongs_to :agenda
has_many :agendaroles through :jointable2
end
class Jointable2 < ActiveRecord::Base
belongs_to :roles
belongs_to :useragenda
end
我不確定語法。 我在正確的軌道上嗎? 我應該如何定義Agenda
和Role
模型?
更新3 :如果我使用類似的東西怎么辦:
class User < ActiveRecord::Base
has_many :roles
has_many :agendas, through: :roles
end
class Role < ActiveRecord::Base
belongs_to :user
belongs_to :agenda
end
class Agenda < ActiveRecord::Base
has_many :roles
has_many :users, through: :roles
end
然后在遷移文件中添加類似以下內容的內容:
class CreateRoles < ActiveRecord::Migration
def change
create_table :roles do |t|
t.belongs_to :user, index: true
t.belongs_to :agenda, index: true
t.string :privilege
t.timestamps
end
end
end
我可以調用@ user.agenda.privilege來獲取給定用戶對給定議程的特權(創建者,編輯者或查看者的“角色”)嗎?
相反,我可以打電話給@ agenda.user.privilege嗎?
好的,我會先說我沒有測試過,但我認為這兩種選擇中的一種應該適合您。
同樣,如果這些has_and_belongs_to_many
表除了關系之外將永遠不需要功能,那么has_and_belongs_to_many
會很好並且更簡潔。
基本的Rails經驗法則:
如果需要將關系模型作為自己的實體使用,請使用has_many:through。 使用舊架構或從未直接使用關系本身時,請使用has_and_belongs_to_many。
首先使用您的示例( http://repl.it/tNS ):
class User < ActiveRecord::Base
has_many :user_agendas
has_many :agendas, through: :user_agendas
has_many :user_agenda_roles, through: :user_agendas
has_many :roles, through: :user_agenda_roles
def agenda_roles(agenda)
roles.where(user_agenda_roles:{agenda:agenda})
end
end
class Agenda < ActiveRecord::Base
has_many :user_agendas
has_many :users, through: :user_agendas
has_many :user_agenda_roles, through: :user_agendas
has_many :roles, through: :user_agenda_roles
def user_roles(user)
roles.where(user_agenda_roles:{user: user})
end
end
class Role < ActiveRecord::Base
has_many :user_agenda_roles
end
class UserAgenda < ActiveRecord::Base
belongs_to :user
belongs_to :agenda
has_many :user_agenda_roles
has_many :roles, through: :user_agenda_roles
end
class UserAgendaRoles < ActiveRecord::Base
belongs_to :role
belongs_to :user_agenda
end
這使用聯接表來保存用戶<=>議程的關系,然后使用表來聯接UserAgenda =>角色。
第二種選擇是使用聯接表來保存用戶<=>議程的關系,並使用另一個聯接表來處理用戶<=>議程<=>角色的關系。 從CRUD的角度來看,此選項將花費更多的時間進行設置,例如驗證用戶是否是該議程的用戶,但具有一點靈活性。
class User < ActiveRecord::Base
has_many :user_agendas
has_many :agendas, through: :user_agendas
has_many :user_agenda_roles
has_many :roles, through: :user_agenda_roles
def agenda_roles(agenda)
roles.where(user_agenda_roles:{agenda: agenda})
end
end
class Agenda < ActiveRecord::Base
has_many :user_agendas
has_many :users, through: :user_agendas
has_many :user_agenda_roles
has_many :roles, through: :user_agenda_roles
def user_roles(user)
roles.where(user_agenda_roles:{user: user})
end
end
class Role < ActiveRecord::Base
has_many :user_agenda_roles
end
class UserAgenda < ActiveRecord::Base
belongs_to :user
belongs_to :agenda
end
class UserAgendaRoles < ActiveRecord::Base
belongs_to :role
belongs_to :user
belongs_to :agenda
end
我知道這是一個很長的答案,但是在這種情況下,我想向您展示解決問題的一種以上方法。 希望能幫助到你
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.