Raunak Joneja
Raunak Joneja

Reputation: 561

Many to many association through another association

So I have a rails app for music events. I have 3 primary table, venues, events, genres

One Venue can have many Events

One Event can have many Genres

One Event has one Venue

One Genre can has many Events

In the events section displaying genres is a simple query and is pretty straightforward. But in the venues section, I wish to display the genres that are there for the events that are happening tonight.

So I added a throught association and a has_many

  has_many :genres, :through => :todays_events

  has_many :todays_events, -> {order(:start_time).where(start_time: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day) }, class_name: 'Event'

This serves my purpose, but I dont belive this is an optimum solution. Is there a better more optimum way to achive the same result?

Upvotes: 0

Views: 48

Answers (1)

Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

I prefer to put the "Events today" logic as part of the Event model, because I like segregating my code into where I think they should belong, and so this is what I would do:

class Event
  belongs_to :venue

  scope :today, -> {
    where(start_time: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).order(:start_time)
  }
end

class Venue
  has_many :events
end

rails console:

venue = Venue.first
events_today = Venue.first.events.today

# or when using as part of the query
available_venues = Venue.where(is_available: true)
available_venues_that_have_events_today = available_venues.joins(:events).where(events: { id: Event.today })

Alternative Solution

class Event
  belongs_to event

  scope :today, -> {
    where(start_time: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)
  }
end

class Venue
  has_many :events
  has_many :events_today, -> { today }, class_name: Event.to_s
end

venue = Venue.first
events_today = Venue.first.events_today

# or when using as part of the query
available_venues = Venue.where(is_available: true)
available_venues_that_have_events_today = available_venues.joins(:events_today)

Upvotes: 1

Related Questions