0

I have scopes defined in an include module like this:

module ActsAsAdjacent

  def self.included(base)

    base.send(:scope, :next, lambda {|id| {:conditions => ["id > ?",id],
       :order => "id ASC", :limit => 1}}) 

    base.send(:scope, :previous, lambda {|id| {:conditions => ["id < ?",id],
       :order => "id DESC", :limit => 1}})     
  end

, the idea being that you can mixin next, previous capability into any ActiveRecord::Base subclass. (The above is a variant of some examples floating around).

The obvious draw back to the above though is that it is assuming a specific column, 'id', whereas that column may not exist in some instances, or there may be a different sort order being used.

Is there a way to do next, previous based on whatever the current sort order is, or how ever the records are layed out in the db.

So for example in the following case,

class User < ActiveRecord::Base

  default_scope :order => 'users.name ASC'

  include ActsAsAdjacent

ActsAsAdjacent would automatically use that sort order to return next, previous.


I guess id will always exist, but it may not be sorted on that.

Mark
  • 1,214
  • 10
  • 24
  • Actually, the :next scope won't even work for id with that default_scope in there, in which case it always returns the very first name record alphabetically. Can't figure that out. – Mark Mar 16 '12 at 15:24
  • Your :next and :previous methods aren't scopes at all. They only return a single method and should be called on an instance, not the class like real scopes. – noodl Mar 16 '12 at 16:33

1 Answers1

1

I think that's a misuse of scopes. How about this?

module ActsAsAdjacent
  def next_by(column)
    self.class.where("#{column} > ?", send(column)).order(column).first
  end

  # .. and the obvious inverse for previous_by
end

# Call it like this:
some_user.next_by(:id)
noodl
  • 17,143
  • 3
  • 57
  • 55
  • That's working - don't know why passing the column name as a string didn't occur to me. (Oh well). You say my scopes above are a misuse. Trying to figure that out. Could you explain then why the scope in the answer by tadman is valid, here: http://stackoverflow.com/questions/5897196/rails-named-scope-inheritance – Mark Mar 16 '12 at 17:24
  • The answer in that other question relates to a method that will be called on the class directly: `User.by_name(name)` whereas your method is called on an instance `some_user.next_by(attribute)`. Make sense? – noodl Mar 16 '12 at 17:33