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 each user, on profile
  • display list of users associated agenda, 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

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -