ruby on rails - Active Record Associations: has_and_belongs_to_many, has_many :through or polymorphic association? -
the ruby on rails app working on allows users create , share agendas other users.
in addition, must able to:
- display list of
agendaseachuser, on profile - display list of
usersassociatedagenda, on agenda's page - when sharing agenda user, define
roleuser, , display role of user on list mentioned right above
i going go has_and_belongs_to_many association between user , agenda models, that:
class user < activerecord::base has_and_belongs_to_many :agendas end class agenda < activerecord::base has_and_belongs_to_many :users end but wondered whether let me , display @user.agenda.user.role list of roles on given agenda page of given user.
and thought should go has_many :through association instead, such as:
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 and although pretty comfortable idea of user having several roles (one each agenda), not sure idea of agenda having several roles (one each user?).
finally, add confusion, read polymorphic association , thought viable solution, if done way instance:
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 does of above solutions sound right situation?
update: doing research, stumbled upon article (from 2012) explaining has_many :through "smarter" choice has_and_belongs_to_many. in case, still not sure fact agenda have many roles.
update 2: suggested in comments @engineersmnkyn, way of solving go 2 join tables. tried implement following code:
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 i not sure syntax though. on right track? , how should define agenda , role models?
update 3: if went like:
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 and then, in migration file, go like:
class createroles < activerecord::migration def change create_table :roles |t| t.belongs_to :user, index: true t.belongs_to :agenda, index: true t.string :privilege t.timestamps end end end would able call @user.agenda.privilege privilege ("role" of creator, editor or viewer) of given user given agenda?
conversely, able call @agenda.user.privilege ?
okay preface saying have not tested think 1 of these 2 choices should work you.
also if these join tables never need functionality besides relationship has_and_belongs_to_many fine , more concise.
basic rails rule of thumb:
if need work relationship model own entity, use has_many :through. use has_and_belongs_to_many when working legacy schemas or when never work directly relationship itself.
first using example (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 this uses join table hold relationship of user <=> agenda , table join useragenda => role.
the second option use join table hold relationship of user <=> agenda , join table handle relationship of user <=> agenda <=> role. option take bit more set crud standpoint things validating if user user agenda allows little flexibility.
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 i know long answer wanted show more 1 way solve problem in case. hope helps
Comments
Post a Comment