I have three models:

User

class User < ApplicationRecord has_many :memberships has_many :parties, through: :memberships end 

Membership

 class Membership < ApplicationRecord belongs_to :user belongs_to :party end 

Party

 class Party < ApplicationRecord has_many :memberships has_many :users, through: :memberships end 

Everything seems to work. Users can be in several groups and in one group several users.

I added the Role field to Membership . It turns out that users can have different roles in different groups. I have a party object, from it I calmly get the desired user , how to get its role correctly? I am writing something like:

 m = user.memberships.find_by party_id: @party.id role = m.role 

I think this is wrong, tell me, please. Maybe there are fundamental fundamental errors?

  • I think this is wrong <- but does it work? - D-side
  • Yes it works. But is it a crutch? - MrAak
  • Maybe. Why do you think so? - D-side
  • Too much code for rails. I think you need to change something to get the role on user.role, for example. - MrAak

1 answer 1

You can define a role method that returns a role at the User model level.

 class User < ActiveRecord::Base has_many :memberships has_many :parties, through: :memberships def role(party) memberships.find_by(party: party).try!(:role) end end 

Then you can get the role more elegantly.

 role = user.role(@party) 
  • Yes indeed! Exactly what is needed! Thanks for the answer. - MrAak
  • He wrote about the same thing, but did not have time :( Small addition: it is better not to use try . Better add a check return unless in_party?(party) - anoam
  • @anoam, what does try and why is it better to do it differently? - MrAak
  • @MrAak It checks if it is called against a Nil object, if it is, it returns nil, if it is another object - it tries to call the method specified as an argument. This way you can prevent a raise call. Probably unless or if here would be really more relevant than try! or new operator &. . In this case, you can more accurately and readably determine what should be returned by the method if the link is not detected. - cheops
  • @MrAak, what he does already written. Instead of using them better, it makes it difficult to read (as a result, support) the code, and lowers the predictability of behavior. - anoam