Reputation: 189
I am looking for a way to query a model based on children in a has_many through association.
I have these models
class User < ApplicationRecord
has_many :members
has_many :squads, through: :members
end
class Squad < ApplicationRecord
has_many :members
has_many :users, through: :members
end
class Member < ApplicationRecord
belongs_to :user
belongs_to :squad
end
I'm basically using the Member class to provide a relationship between User and Squad, so it can hold membership information such as role, position, number, .etc
The goal is to have the Member
model store User
membership info as it relates to any Squad
. A User can be an owner of one squad, be a member of another, and not be a member of yet another squad.
I am trying to display a Join link in my index.html.erb for all User's that do not have any member connection to a squad.
Currently, working with
<% @squads.each do |squad| %>
<td><%= squad.name %></td>
<% if Squad.includes(:members).where( 'members.user_id' => params[:users]).exists? %>
<td><%= link_to 'Join', join_squad_path(:id => squad) %></td>
<% end %>
<% end %>
with the primary line being
<% if Squad.includes(:members).where( 'members.user_id' => params[:users]).exists? %>
also tried stuff such as
User.includes(:squads, :members).where('squads.id = ? AND members.users = ?', squad, current_user)
u = squad.users.includes(:member).where('member.user = ?', current_user)
Member.where.not("squad = #{squad.id}").find(user: current_user.id)
I have an instance variable for each |squad| and have current_user.id available for the logged in user (using Devise)
Referencing Ruby on Rails Guide: Association Basics - the has many through association
Upvotes: 1
Views: 462
Reputation: 1951
Do you want to show the button if the logged user is not a member of each squad? If so...
has_many
association provides the method other_ids
which returns an array of the associated objects' ids (in your case squad.user_ids
). So you can check if the current user's id is in that array:
<% @squads.each do |squad| %>
<td><%= squad.name %></td>
<% unless squad.user_ids.include?(current_user.id) %>
<td><%= link_to 'Join', join_squad_path(id: squad) %></td>
<% end %>
<% end %>
Upvotes: 2
Reputation: 841
User.includes(:members).where(members: { id: nil }).or(User.includes(:members).where.not(members: { squad_id: squad.id }))
Explanation:
User.includes(:members).where(members: { id: nil })
To query users that have no member record (belong to no squad)
User.includes(:members).where.not(members: { squad_id: squad.id })
To query users that do have member record but not member of the target squad.
Upvotes: 2