3

Given a model called Event (id, name) and a model called EventUser (event_id, user_id), I iterate through Events. During this iteration, I display whether or not the logged-in user is attending the Event based on the existence of an EventUser existing. Standard stuff.

I know that I can perform a query against each Event, and have something such as

class Event < ActiveRecord::Base

  def user_attending?(user)
    event_users.find_by(:user_id => user.id)
  end 

end

but that's not very clean, performant, or extensible.

I could load all of the User's attending events from the list of Events, say,

@events = Event.all 
@attending_events = current_user.event_users.where(:event_id => @events.map(&:id))

which is better, but not great. I could with this add an accessor to my Event model and iterate through @attending_events but that seems icky.

I suppose in my ideal scenario, I would be able to join the two tables on events.id = event_users.event_id, and where event_users.user_id = current_user.id and if that row exists, I'd be able to label the/a resulting column as attending

How can I do this with Arel or ActiveRecord, or even SQL? Using PostgreSQL over here.

3 Answers3

0

Do you want something like this? Sorry for lucky guessing, but if I didn't understood your question, could you be more concrete, which problem you're aiming to solve?

class Event < ActiveRecord::Base
  has_many :user_events, class_name: 'UserEvent', inverse_of: :event
  has_many :users, through: :user_events
end

possible kinds of usage

1) suggested usage:

Event.joins(:user_events).where(user_events: {user_id: user.id}).any?

2) filtering by user-details. Keep in mind that joins takes the defined has_many relation from the Event model, but where takes the table-name. Just in case when the has_many relation-name and table-name are differing

Event.joins(:users).where(users: {name: 'Harry'}).any?

3) alternative usage with concrete record instead of id from Rails - check if record exists in has_many association

current_event.users.exists?(user.id)

Community
  • 1
  • 1
loybert
  • 416
  • 1
  • 3
  • 12
0

I was thinking it could be simply:

class User < ActiveRecord::Base
  has_many :user_events, class_name: 'UserEvent', inverse_of: :event
  has_many :events, class_name: 'Event'
end

Then you just do @attending_events = current_user.events

In your view then you can get out whatever you store for that each Event which current_user is attending.

matiss
  • 747
  • 15
  • 36
-1

I'm confused. Assuming:

  • you have set up has_many :events, through: :event_users in your User model,
  • you have an instance variable (presumable in your controller) something like @user_events = user.events
  • you have an instance variable (also presumably in your controller) something like @events = Event.all

In your view, isn't it something like (assuming erb):

<% @events do |event| %>
  <% if @user_events.include?(event) %>
    ... do some stuff
  <% else %> 
    ... do some other stuff
  <% end %>
<% end %>

Maybe I'm being dense and entirely missing the point... If so, apologies in advance.

jvillian
  • 19,953
  • 5
  • 31
  • 44
  • I think that what OP wants to do is avoid loading the user_events in another query entirely and instead add an alias to the Events query that indicates if there's a matching row based on the criteria he provided. – Josh Brody Jan 03 '18 at 21:40
  • I'm not sure what "add an alias to the Events query" means. But, unless this is a production system with either high volume or a large number of records, this seems like a bit of preemptive optimization to me. No? – jvillian Jan 03 '18 at 21:46