Reputation: 2900
In my Rails 6 app I've got model Journey with defined active
scope:
class Journey < ApplicationRecord
has_many :users, through: :journey_progresses
has_many :journey_progresses, dependent: :destroy
scope :active, -> { where(is_deleted: false) }
end
In my endpoint I want to show user journey_progress and for serializer journey itself. To do so I'm using below query which works well
def query
current_user.journey_progresses.includes(:journey)
end
How to modify above query to show only active journeys? I tried to just add where to be like current_user.journey_progresses.includes(:journey).where(is_deleted: false)
but I'm getting an error:
Caused by PG::UndefinedColumn: ERROR: column journey_progresses.is_deleted does not exist
According to this answer I tried with current_user.journey_progresses.includes(:journey).where(journey: {is_deleted: false} )
but I'm getting another error:
Caused by PG::UndefinedTable: ERROR: missing FROM-clause entry for table "journey"
What is the right syntax for that sort of action?
Upvotes: 3
Views: 2133
Reputation: 2134
You are misusing includes
here. includes
is only for optimization, to reduce number of queries going to the database.
Since you want to filter rows based on values in journey
, you need to join it:
current_user.journey_progresses.joins(:journey)
As a general advice for these kind of problems I would recommend looking at the Rails log to see what SQL is generated at the end. Dealing with multiple has_many
, scope
, include
, etc. can become confusing quickly.
UPDATE
You can actually combine joins
with includes
like this:
Foo.includes(:bars).where('bars.name = ?', 'example').references(:bars)
See https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-includes
Upvotes: 2
Reputation: 1521
current_user.journey_progresses.includes(:journey).where(journey: {is_deleted: false} )
The above syntax is available from Rails 5.
You could try below possible ways,
In JourneyProgress Model
class JourneyProgress < ApplicationRecord
belongs_to :active_journey, -> { where(is_deleted: false) }, class_name: 'Journey'
end
and include the association while querying.
current_user.journey_progresses.includes(:active_journey)
default_scope -> { where(is_deleted: false) }
Upvotes: 2
Reputation: 36860
You can merge a scope of a joined model.
current_user.journey_progresses.joins(:journey).merge(Journey.active)
This is better than testing for the is_deleted
boolean because in future, if the definition of what makes a journey active changes, you won't need to modify the above line.
Upvotes: 6
Reputation: 3126
Can you try the following?
current_user
.journey_progresses.
.joins(:journey)
.where("journeys.is_deleted = ?", false)
Upvotes: 2