Using AND conditions and Between in Rails Scopes

172 Views Asked by At

I'm trying to create a scope to return all records that fall between a certain range and date.

I have a method that accomplishes this but I'm trying to refactor it.

Original Method:

  def self.find_by_time facility_id, start_time_string
    day_of_week = start_time_string.to_date.wday
    start_time= start_time_string.to_datetime.strftime("%H:%M")
    self
    .where("facility_id = ? AND (? BETWEEN start_day AND end_day) AND (? BETWEEN start_time AND end_time)",
     facility_id, day_of_week, start_time)
  end

This works fine but I don't like the use of SQL here and I'd like to use scopes and squeel to clean it up. I'd also prefer to passing in the Facility object directly instead of just the id.

This is what I'm trying:

  scope :within_weekday, -> (weekday) {where {start_day <= weekday} & {end_day >= weekday}}
  scope :within_time, -> (time) {where {start_time <= time} & {end_time >= time}}

  def self.find_by_time facility, start_time
    day_of_week = start_time_string.to_date.wday
    start_time= start_time_string.to_datetime.strftime("%H:%M")
    self.find_by(facility: facility).within_date(day_of_week).within_time(start_time).first
  end

Some errors I'm getting:

    SyntaxError: /vagrant/playtoday/app/models/pricing_period.rb:12: syntax error, unexpected '}', expecting =>
...weekday} & {end_day >= weekday}}
...                               ^
/vagrant/playtoday/app/models/pricing_period.rb:13: syntax error, unexpected '}', expecting =>
...e <= time} & {end_time >= time}}
...                               ^

Is it even possible to use conditions in scopes? I haven't been able to figure that out yet.

2

There are 2 best solutions below

0
Wizard of Ogz On BEST ANSWER

Looks like you have syntax errors. You should be using parentheses instead of curly braces within the where blocks.

scope :within_weekday, -> (weekday) { where { (start_day <= weekday) & (end_day >= weekday) }
scope :within_time, -> (time) { where { (start_time <= time) & (end_time >= time) }
1
sawa On

There is no operator =< (not only undefined, but is illegal). You may have intended <=.

How to memorize:

  • The token => is reserved for hash literals and for receiving the error in rescue. Hence "equal to or greater than" cannot be expressed by that. It is expressed by >=.
  • You want the operator notation to be consistent; since there is >=, you want <= (and not =<) for "equal to or less than".