Reputation: 906
I've been at this for ages and can't get it right. I have a gig
model and a couple of tables. In each table I need to show only gigs that meet certain requirements but there is one table that I cannot figure out.
This table must contain gigs where:
not expired (date attribute NOT in the past)
expired BUT with filled == true (date attribute in past but filled attribute true)
The table must NOT contain gigs where:
my scopes:
scope :expiredr, -> { where('gigzonetime <= ?', Time.current.to_datetime)}
scope :notfilled, -> {where(filled: false)}
scope :filled, -> {where(filled: true)}
scope :expired_and_filled, ->() {self.expiredr.merge(self.filled)}
scope :expired_and_notfilled, ->() { self.expiredr.merge(self.notfilled) }
I have tried loads of variations, eg.
Controller:
def dashboard
if user_signed_in? && !current_user.try(:artist?)
@activegigs = current_user.gigs.notcompleted.where.not(:expired_and_notfilled)
@q = @activegigs.ransack(params[:q])
@dashgigs = @q.result(distinct: true).order(filled: :desc, reviewed: :desc, date: :asc).page(params[:page]).per(20)
else
redirect_to(root_url)
flash[:danger] = "This page is for registered hosts only"
end
end
which gives an
RuntimeError at /gigs/dashboard
unsupported: Symbol
OR
@activegigs = current_user.gigs.notcompleted && current_user.gigs.expired_and_filled && current_user.gigs.notexpired
Which only shows expired_and_filled gigs.
I am not sure how to negate the expired_and_notfilled scope or if that's even necessary. Any suggestions would be appreciated, thanks.
Upvotes: 1
Views: 119
Reputation: 1428
OK, so the logic seems to only need to be !expired OR filled. There is no need for the !expired OR (expired and filled) NOT (expired and filled) logic tree. This constructs a simple where query:
.where('gigzonetime > ? OR filled IS TRUE', Time.current.to_datetime)
Upvotes: 1
Reputation: 6603
Using ransack, we need to have an OR condition for not_expired
and expired_and_filled
to satisfy the table content as you have mentioned.
Add a new scope, and whitelist the two scopes to be filterable by ransack using ransackable_scopes
(documentation here)
# gig.rb
scope :not_expired, -> { where('gigzonetime > ?', Time.current.to_datetime) }
def self.ransackable_scopes(auth_object = nil)
[:not_expired, :expired_and_filled]
end
Now we can combine the query using the advanced ransack using 'OR' instead of the default 'AND' (documentation here)
You need to make sure that
params[:q] == {m: 'or', not_expired: true, expired_and_filled: true }
You can pass m: 'or'
through a hidden_field
so that params
will look like above.
The following should then work properly already.
@q = Gig.ransack(params[:q])
@gigs = @q.result(distinct: true).order(filled: :desc, reviewed: :desc, date: :asc).page(params[:page]).per(20)
@gigs
should now include gigs not_expired and gigs expired_and_filled together
Upvotes: 1