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
agendas
eachuser
, on profile - display list of
users
associatedagenda
, on agenda's page - when sharing agenda user, define
role
user, , 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