Search code examples
ruby-on-rails-4mongoidmongoid4

scope not working on Mongoid (undefined method `to_criteria')


I invoke ReleaseSchedule.next_release in other controller

and got the following error

NoMethodError (undefined method `to_criteria' for #<ReleaseSchedule:0x007f9cfafbfe70>):
  app/controllers/weekly_query_controller.rb:15:in `next_release'

releae_schedule.rb

class ReleaseSchedule
  scope :next_release, ->(){ ReleaseSchedule.where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first }
end

Solution

  • That's not really a scope at all, that's just a class method wrapped up to look like a scope. There are two problems:

    1. You're saying ReleaseSchedule.where(...) so you can't chain the "scope" (i.e. ReleaseSchedule.where(...).next_release won't do what it is supposed to do).
    2. Your "scope" ends in first so it won't return a query, it just returns a single instance.

    2 is probably where your NoMethodError comes from.

    If you really want it to be a scope for some reason then you'd say:

    # No `first` or explicit class reference in here.
    scope :next_release, -> { where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at) }
    

    and use it as:

    # The `first` goes here instead.
    r = ReleaseSchedule.next_release.first
    

    But really, you just want a class method:

    def self.next_release
      where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first
    end
    

    The scope macro is, after all, just a fancy way to build class methods. The only reason we have scope is to express an intent (i.e. to build queries piece by piece) and what you're doing doesn't match that intent.