ActiveRecord query for three models?

I have three models:

class User < ActiveRecord::Base
 has_many :projects, :through => :permissions

class Permission < ActiveRecord::Base
 belongs_to :user
 belongs_to :project
 belongs_to :role

class Project < ActiveRecord::Base
 has_many :users, :through => :permissions

It is very simple, taking into account the above, to get all users of the project: @project.users

But what I want to do is get something like this: Get all users in all user projects.

So, if a user has 3 projects, each of which has 5 users. I want to complete a query to get all 15 users in all user groups.

I am trying with this.

 current_user.projects.users 

but Rails doesn't really like it. current_user.projects works fine, but not users.

Suggestions? Ideas? thank!

UPDATED CODE 3 based on noodl comments

  scope :suggestedContacts, lambda { |user|
    users_from_projects = user.projects.reduce([]) {|all_users,prj|
      all_users + prj.users
    }.uniq
  }

ERRORS:

NoMethodError (undefined `includes_values' method for #):

+3
source share
6 answers

My two solutions:

  • , ,
  • , SQL, N + 1
  • , , , ..

1.

.
rails 3.0.x has_many_through, , 3.1

class User < ActiveRecord::Base
 has_many :permissions
 has_many :projects, :through => :permissions
 has_many :users_in_projects, :through => :projects, :source => :user # chain the relation

class Permission < ActiveRecord::Base
 belongs_to :user
 belongs_to :project

class Project < ActiveRecord::Base
 has_many :users, :through => :permissions

current_user.users_in_projects

2.

( , , ). , .

class User < ActiveRecord::Base
 has_many :permissions
 has_many :projects, :through => :permissions, :include => :users # eager load users

class Permission < ActiveRecord::Base
 belongs_to :user
 belongs_to :project

class Project < ActiveRecord::Base
 has_many :users, :through => :permissions

current_user.projects.map(&:users).reduce(&:+).uniq_by(&:id) 
# returns users in current_user projects, one query, some computations
+3

@noodl , , "" . , . , , , , , "" ( , ).

class User

  has_many :project_users, :class_name => "User", :finder_sql => 'select u.* from users u join permissions pp on pp.user_id=u.id join projects p on pp.project_id=p.id where project_id in (select project_id from permissions pp2 where user_id=#{id}) and pp.user_id != #{id} group by u.id'

end

, :

user = User.find(1)
=> #<User id: 1, name: "Stephen">
user.project_users
=> [#<User id: 2, name: "Kathleen">, #<User id: 3, name: "Anne">]
+2

, , .

users = current_user.projects.map(&:users).flatten.uniq
+1

, Enumerable. , ():

current_user.projects.each {|prj|
  prj.users.each{|usr|
    #do stuff
  }
}

( ),

users_from_projects = current_user.projects.reduce([]) {|all_users,prj|
  all_users = all_users + prj.users
}.uniq

EDIT to fix, thanks pointing it to noodl.

0
source

In your user class add:

 has_many :users, :through => :permissions

So it will look like this:

 class User < ActiveRecord::Base
   has_many :projects, :through => :permissions
   has_many :users, :through => :permissions
0
source

You need to upload your associations

class User < ActiveRecord::Base
  has_many :projects, :through => :permissions, :include => :users
  has_many :permissions, :include => {:project => :users}
  …
end
-1
source

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


All Articles