问题
We have a method in our model occurs_on?
Enrollment.first.occurs_on?(Date.current)
which returns true if an enrollment falls on a Date (and false if not). Enrollments have a recurring schedule and it's not possible to do a db query for occurs_on?
without doing calculations in Ruby. It's all working fine but this is throwing off our pagination. Is it possible to define a scope that doesn't depend on a database column? For example something like
scope :occurs_today, -> { occurs_on?(Date.current) }
I'm hoping it's possible so we can use pagination and also chain the scope, for example
Enrollment.active.occurs_today
回答1:
All what Jon wrote is correct, however, scopes
are basically only class methods on your model class. This means you could replicate a similar behaviour depending on which library you use for pagination.
Example
class Enrollment
scope :active -> { where(active: true) }
def self.occurs_today
records = select { |record| record.occurs_on?(Date.current) }
# https://github.com/kaminari/kaminari#paginating-a-generic-array-object
Kaminari.paginate_array(records, total_count: count)
end
end
Enrollment.active.occours_today.page(2)
This of course has a few limitations
- You still need to load all records from the database and filter them in Ruby. One main benefit of pagination is to load less data so it's not really what you should do.
- The 'scope' does not return an ActiveRecord relationship but e.g. an Array so you have to use the method as the last one because
Enrollment.occurs_today.active
will throw aundefined method active
.
回答2:
No, what you're suggesting isn't possible because scopes are just used to modify the SQL query generated by ActiveRecord.
However, you can probably create a scope that achieves what you're looking for. Whilst you may not be familiar/comfortable with it, and it will likely require you to write code specific to your DB of choice, you can almost certainly replicate the logic you require for identifying whether your Enrollment
occurs on a specific date within your DB query.
回答3:
This seems to work. I'm sure it's inefficient but it's giving us correct results and pagination works on this
scope :occurs_today, -> { where(id: all.select { |s| s.occurs_on?(Date.current) }.map(&:id)) }
来源:https://stackoverflow.com/questions/63927562/is-it-possible-to-define-a-scope-for-a-non-db-column