簡體   English   中英

活動記錄關聯:has_and_belongs_to_many,has_many:通過還是多態關聯?

[英]Active Record Associations: has_and_belongs_to_many, has_many :through or polymorphic association?

我正在使用的Ruby on Rails應用允許users創建和與其他users共享agendas

此外,我們必須能夠:

  • 在其個人資料上顯示每個useragendas列表
  • 在議程頁面上顯示與agenda關聯的users列表
  • 與其他用戶共享議程時,請為該用戶定義一個role ,然后在上面提到的列表中顯示該用戶的角色

我打算在useragenda模型之間建立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 :throughhas_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

我不確定語法。 我在正確的軌道上嗎? 我應該如何定義AgendaRole模型?

更新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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM