ruby-on-railsrubyruby-on-rails-4squeel

Using AND conditions and Between in Rails Scopes


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.


Solution

  • 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) }