Permalink
Browse files

Add previous and next, since this seems to be a common thing that peo…

…ple love doing some Wheel Re-invention of. Thought I'd do my own. Hat-tip Sam Elliott.
  • Loading branch information...
Ryan Bigg
Ryan Bigg committed Mar 25, 2010
1 parent abb42aa commit 7a39e1a468502b7969951a96140e9562a88522cf
Showing with 62 additions and 4 deletions.
  1. +22 −1 README.markdown
  2. +3 −2 by_star.gemspec
  3. +6 −0 lib/by_star.rb
  4. +13 −0 lib/neighbours.rb
  5. +18 −1 spec/by_star_spec.rb
View
@@ -32,7 +32,7 @@ You can treat all `by_*` methods exactly how you would treat `named_scope`s: the
Where `my_special_scope` is a `named_scope` you have specified.
-All the `by_*` methods take a block which will then scope the find based on the options passed into it. You can also specify these options for each method, but the syntax may differ. The supported options are the same options that are supported by `find` from ActiveRecord. Please note that if you want to use conditions you *have* to use this syntax:
+All the `by_*` methods, with the exception of `previous` and `next`, take a block which will then scope the find based on the options passed into it. You can also specify these options for each method, but the syntax may differ. The supported options are the same options that are supported by `find` from ActiveRecord. Please note that if you want to use conditions you *have* to use this syntax:
Post.by_month(1) { { :include => "tags", :conditions => ["tags.name = ?", 'ruby'] } }
@@ -361,6 +361,26 @@ To find records up to a certain time from the current time:
Post.up_to_6_weeks_from_now
+## Previous (`previous`)
+
+To find the record prior to this one call `previous` on any model instance:
+
+ Post.last.previous
+
+You can specify a field also:
+
+ Post.last.previous("published_at")
+
+## Next (`next`)
+
+To find the record after this one call `next` on any model instance:
+
+ Post.last.next
+
+You can specify a field also:
+
+ Post.last.next("published_at")
+
## Not using created_at? No worries!
If your database uses something other than `created_at` for storing a timestamp, you can specify the field option like this:
@@ -388,6 +408,7 @@ Unfortunately I forget who exactly prompted me to write the plugin, but I would
* August Lilleas (leethal)
* gte351s
* Thomase Sinclair (anathematic)
+* Sam Elliott (lenaryg)
* The dude(s) & gal(s) who created Chronic
## Suggestions?
View
@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = %q{by_star}
- s.version = "0.6.3"
+ s.version = "0.6.4"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Ryan Bigg", "Mislav Marohni\304\207"]
- s.date = %q{2010-03-14}
+ s.date = %q{2010-03-25}
s.description = %q{ActiveRecord extension for easier date scopes and time ranges}
s.email = %q{radarlistener@gmail.com}
s.extra_rdoc_files = [
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
"Rakefile",
"VERSION",
"by_star.gemspec",
+ "cleaner.rb",
"init.rb",
"lib/by_star.rb",
"lib/calculations.rb",
View
@@ -3,13 +3,15 @@
require 'range_calculations'
require 'time_ext'
require 'vanilla'
+require 'neighbours'
Dir[File.dirname(__FILE__) + '/calculations/*.rb'].each { |file| require file }
require 'calculations'
module ByStar
def self.included(base)
base.extend ClassMethods
+ base.send(:include, InstanceMethods)
end
module ClassMethods
@@ -18,6 +20,10 @@ module ClassMethods
include Vanilla
include Calculations
end
+
+ module InstanceMethods
+ include Neighbours
+ end
class ParseError < Exception; end
class MonthNotFound < Exception; end
View
@@ -0,0 +1,13 @@
+module ByStar
+ module Neighbours
+ # Find the previous record to this.
+ def previous(field="created_at")
+ self.class.past(self.send(field)) { { :order => "#{field} DESC" }}.first
+ end
+
+ # Find the next record to this.
+ def next(field="created_at")
+ self.class.future(self.send(field)) { { :order => "#{field} ASC" }}.first
+ end
+ end
+end
View
@@ -641,6 +641,23 @@ def size(*args)
end
+ describe "directional finders" do
+ subject { Post.today.first }
+
+ describe "previous" do
+ it "should find the post previous to it" do
+ subject.previous.text.should eql("Yesterday's post")
+ end
+ end
+
+
+ describe "next" do
+ it "should find the post next to it" do
+ subject.next.text.should eql("Tomorrow's post")
+ end
+ end
+ end
+
describe "chaining of methods" do
# a by_star and a by_direction method, in that order
it "should be able to chain today and past" do
@@ -653,7 +670,7 @@ def size(*args)
end
end
-
+
describe "edge cases" do
# This method previously generated sql like: `day_entries`.`spent_at`.`spent_at`.`spent_at`.`spent_at`
# Which is *obviously* incorrect and #omg worthy.

0 comments on commit 7a39e1a

Please sign in to comment.