Has_many multiple reach through relationships in Rails 4

I want to model such a relationship between the User and Event models.

So I started with the following classes:

class User < ActiveRecord::Base ... end class Attendance < ActiveRecord::Base # with columns user_id and event_id ... end class Event < ActiveRecord::Base has_many :attendances has_many :users, :through => :attendances ... end 

So far, everything is in order: I can assign users and get access to attendance. But now I want to bring the state into the game, so that I can distinguish, for example, between "present", "without a valid side", ... users. My first attempt was:

 class Event < ActiveRecord::Base has_many :attendances has_many :users, :through => :attendances has_many :unexcused_absent_users, -> { where :state => 'unexcused' }, :through => :attendances, :source => :user ... end 

(: the source must be specified, because otherwise it will look for membership in an association with the name "unscused_absent_users") The problem here is that the where predicate is evaluated in the "users" table.

I do not know how to solve this β€œcorrectly” without introducing new tables / connection models for each state. Moreover, each user can be in the same state for each event, I think that a solution with one presence model makes sense.

Do you have an idea how to do it right?

+4
source share
3 answers

You can simply narrow the scope for the correct table:

  has_many :unexcused_absent_users, -> { where(attendances: {state: 'unexcused'}) }, :through => :attendances, :source => :user 

Find out better, add this area to the attendance model and combine it into:

 class Attendance < ActiveRecord::Base def self.unexcused where state: 'unexcused' end end class Event < ActiveRecord::Base has_many :unexcused_absent_users, -> { merge(Attendance.unexcused) }, :through => :attendances, :source => :user end 
+4
source

I found a workaround, but I still think it's ugly.

 class Event < ActiveRecord::Base has_many :user_attendances, :class_name => 'Attendance' has_many :users, :through => :user_attendances, :source => :user has_many :unexcued_absent_user_attendances, -> { where :state => 'unexcused'}, :class_name => 'Attendance' has_many :unexcused_absent_users, :through => :unexcued_absent_user_attendances, :source => :user end 

In general: for each state I want, I have to introduce a new has_many relationship with scope and, moreover, and taking into account the has_many-through relationship.

+1
source

can this work for you?

 class Event < ActiveRecord::Base has_many :attendances has_many :users, :through => :attendances def unexcused_absent_users User.joins(:attendances) .where(:state => 'unexcused') .where(:event_id => self.id) end end 

in rails 3+ methods are basically the same as areas, but less confusing (in my opinion), they cling

 event = Event.find(xxxx) event.unexcused_absent_users.where("name LIKE ?", "Smi%") 
+1
source

Source: https://habr.com/ru/post/1488964/


All Articles