I've tried to implement conditional chaining and this is what I got:
Controller index action code:
@range_start = params[:range_start]
@range_stop = params[:range_stop]
Contract.within_range(@range_start, @range_stop)
Model code:
def self.within_range(range_start = Date.today - 1.month, range_stop = nil)
self.started_after(range_start).started_before(range_stop)
end
def self.started_after(range_start)
if range_start.blank?
self
else
self.where('start_date >=?', range_start)
end
end
def self.started_before(range_stop)
if range_stop.blank?
self
else
self.where('start_date<=?', range_stop)
end
end
It works, but does not looks good. I tried to improve it a bit using tap
, without success. How this code can be improved?
UPDATE: In can be converted to inline conditional, but maybe something else can be improved?
range_start.blank? ? self : self.where('start_date >=?', range_start)
UPDATE2: If range_stop
is not set, this code is not really works, started_after
condition does not apply.
What I have to return from started_before
to do not loose first condition?
Time has passed and the solution of denis.peplin is already deprecated. Otherwise it's right, you need a relation for chaining. So instead of using scoped
you should use all
like this:
def self.started_before(range_stop)
if range_stop.blank?
all
else
where('start_date<=?', range_stop)
end
end
But you could also write this as a scope for more brevity:
scope :started_before, ->(range_stop){ range_stop.blank? ? all : where('start_date<=?', range_stop) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With