Skip to content

Instantly share code, notes, and snippets.

@danielbeardsley
Created April 4, 2011 23:10
Show Gist options
  • Save danielbeardsley/902671 to your computer and use it in GitHub Desktop.
Save danielbeardsley/902671 to your computer and use it in GitHub Desktop.
Adds .previous and .next named scopes to your Active Record model, treating the records in your database like a sequential list with an order of your choosing.
# Adds .previous and .next class methods to your model treating the records in your database like a sequential list
#
# Put this in your model definition:
# acts_as_sequential :column => :created_at # you can also use the :dir => 'DESC' option (ASC is the default)
#
# Then use it like this:
# Model.next(current_record) -> next record in sequence
# Model.other_named_scope.previous(current_record) -> previous record in sequence
#
module ActsAsSequential
class << self
def included(base)
base.extend ClassMethods
end
end
module ClassMethods
def acts_as_sequential opt={}
column = opt[:column]
table_name = self.table_name
directions = [:next, :previous]
desc_condition = "#{table_name}.#{column} <= ? AND #{table_name}.id != ?"
asc_condition = "#{table_name}.#{column} >= ? AND #{table_name}.id != ?"
directions.reverse! if opt[:dir].to_s =~ /desc/i
class_eval %Q?
def self.#{directions.pop}(record)
self.first(
:order => "#{table_name}.#{column} DESC",
:conditions => ["#{desc_condition}", record["#{column}"], record.id]
)
end
?
class_eval %Q?
def self.#{directions.pop}(record)
self.first(
:order => "#{table_name}.#{column} ASC",
:conditions => ["#{asc_condition}", record["#{column}"], record.id]
)
end
?
end
end
end
if Object.const_defined?("ActiveRecord")
ActiveRecord::Base.send(:include, ActsAsSequential)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment