0

I'm trying to solve a seemingly simple AR problem I'm having. I can't figure out how to return a list of events that have 1 or more attendees, and the docs examples use cache_control which I don't want to use.

I have a simple event model with a has_many relationship:

class Event < ActiveRecord::Base
  has_many :attendees
end

and an attendees model that belongs to event

class Attendees < ActiveRecord::Base
  belongs_to :event
end

But some events will have 0 attendees. So what's the ActiveRecord way of doing this without using cache_control or writing a custom SQL statement?

It seems like it would be something like:

Event.where(attendees.count > 0)

but I keep getting a column error.

3 Answers3

0

To get only events with attendees you can do: Event.joins(:attendees).uniq.all

Calling all at the end returns an array whereas dropping it will leave you with an activerecord relation.

bkunzi01
  • 4,504
  • 1
  • 18
  • 25
0

you can use where method chained with not to do this

Event.where.not(id: Attendee.select(:event_id))
sa77
  • 3,563
  • 3
  • 24
  • 37
0

If you do a LEFT INNER JOIN only records with a match in the join table will be returned. So you don't actually need to perform a count.

Event.joins(:attendees)

Will thus only give you events which have attendees. The opposite would be a LEFT OUTER JOIN which returns rows from events even if there is no corresponding rows in attendees.

Counter caches on the other hand can be beneficial for performance since it avoids a COUNT query on the associated table if you want to use a lazy loading association. This can be useful when using fragment caching or if the query to the associated table is expensive.

<%# counter cache avoids query %>
<% cache(event) do %>
<ul>
  <%# only perform query if cache is stale %>
  <% event.attendees.each do |a| %> 
  <li><%= link_to a.name, a %></li>
  <% end %>
<ul>
<% end if event.attendees.any? %>
Community
  • 1
  • 1
max
  • 96,212
  • 14
  • 104
  • 165
  • If you really wanted to do a count you would need to join the table or perform a subselect. Your approach does not work since the `attendees` table is not in the `FROM` clause in the query. – max Dec 04 '16 at 09:39