Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for Mongoid (adapter for MongoDB). It's basically a mon…

…key-patch file (see: lib/mongoid/by_star.rb) with a small change at the end of lib/by_star.rb to detect inclusion of ActiveRecord and/or Mongoid.

I refactored the specs so that the exact same specs can be run by both Mongoid and ActiveRecord seamlessly (core specs now moved to /spec/by_star/generic). I am able to pass 49/60 ActiveRecord specs (i.e. prior to this commit; I have not introduced any regressions) and 50/60 Mongoid test--basically the same ones fail, the only exception is "by year/should be able to order the result set" which I believe is genuinely broken on Mongoid due to API differences.

Updated readme as well.

Fixes #14
  • Loading branch information...
commit 71d385de1decd9f6a86ede7c39abce80dafa50c9 1 parent 3cd30c6
@johnnyshields johnnyshields authored committed
Showing with 841 additions and 403 deletions.
  1. +2 −0  .travis.yml
  2. +55 −5 README.markdown
  3. +1 −0  by_star.gemspec
  4. +11 −3 lib/by_star.rb
  5. +4 −0 lib/by_star/by_fortnight.rb
  6. +19 −5 lib/by_star/by_month.rb
  7. +32 −0 lib/by_star/by_quarter.rb
  8. +5 −3 lib/by_star/by_week.rb
  9. +3 −0  lib/by_star/by_weekend.rb
  10. +5 −3 lib/by_star/by_year.rb
  11. +1 −1  lib/by_star/version.rb
  12. +83 −0 lib/mongoid/by_star.rb
  13. +50 −0 spec/by_star/active_record/active_record_spec.rb
  14. +0 −60 spec/by_star/by_day_spec.rb
  15. +0 −82 spec/by_star/by_direction_spec.rb
  16. +0 −46 spec/by_star/by_fortnight_spec.rb
  17. +0 −60 spec/by_star/by_month_spec.rb
  18. +0 −39 spec/by_star/by_week_spec.rb
  19. +0 −12 spec/by_star/by_weekend_spec.rb
  20. +0 −57 spec/by_star/by_year_spec.rb
  21. +44 −0 spec/by_star/mongoid/mongoid_spec.rb
  22. +62 −0 spec/by_star/shared/by_day.rb
  23. +85 −0 spec/by_star/shared/by_direction.rb
  24. +47 −0 spec/by_star/shared/by_fortnight.rb
  25. +109 −0 spec/by_star/shared/by_month.rb
  26. +33 −0 spec/by_star/shared/by_quarter.rb
  27. +41 −0 spec/by_star/shared/by_week.rb
  28. +13 −0 spec/by_star/shared/by_weekend.rb
  29. +54 −0 spec/by_star/shared/by_year.rb
  30. +13 −0 spec/fixtures/active_record/models.rb
  31. 0  spec/fixtures/{ → active_record}/schema.rb
  32. +65 −0 spec/fixtures/mongoid/models.rb
  33. +0 −16 spec/fixtures/{models.rb → shared/seeds.rb}
  34. +4 −11 spec/spec_helper.rb
View
2  .travis.yml
@@ -21,3 +21,5 @@ rvm:
- 1.8.7
- 1.9.3
- 1.9.2
+
+services: mongodb
View
60 README.markdown
@@ -1,7 +1,7 @@
# by_*
-by_* (by_star) is a plugin that allows you to find ActiveRecord objects given certain date objects.
+by_* (by_star) is a plugin that allows you to find ActiveRecord and/or Mongoid objects given certain date objects.
## Installation
@@ -11,7 +11,17 @@ Install this gem by adding this to your Gemfile:
gem 'by_star', :git => "git://github.com/radar/by_star"
```
-Then run `bundle install`. Hey presto, it's done!
+Then run `bundle install`.
+
+If you are using ActiveRecord, you're done!
+
+Mongoid users, please include the Mongoid::ByStar module for each model you wish to use the functionality. This is the convention among Mongoid plugins.
+
+```ruby
+class MyModel
+ include Mongoid::Document
+ include Mongoid::ByStar
+```
## What it does
@@ -23,6 +33,8 @@ This was originally crafted for only finding objects within a given month, but n
* A given week
* A given weekend
* A given day
+* A given quarter
+* The weeks of a given month as shown on a calendar
* The current weekend
* The current work week
* The Past
@@ -107,6 +119,14 @@ If you have a Time object you can use it to find the posts:
This will find all the posts in November 2012.
+## By Calendar Month (`by_calendar_month`)
+
+Finds records for a given month as shown on a calendar. Includes all the results of `by_month`, plus any results which fall in the same week as the first and last of the month. Useful for working with UI calendars which show rows of weeks.
+
+ Post.by_calendar_month
+
+Parameter behavior is otherwise the same as `by_month`
+
## By Fortnight (`by_fortnight`)
Fortnight numbering starts at 0. The beginning of a fortnight is Monday, 12am.
@@ -141,11 +161,11 @@ To find records based on a week, you can pass in a number (representing the week
Post.by_week(36)
-This will return all posts in the 36th week of the current year.
+This will return all posts in the 37th week of the current year (remember week numbering starts at 0).
Post.by_week(36, :year => 2012)
-This will return all posts in the 36th week of 2012.
+This will return all posts in the 37th week of 2012.
Post.by_week(Time.local(2012,1,1))
@@ -174,6 +194,28 @@ You can also pass a string:
This will return all posts for the given day.
+## By Quarter (`by_quarter`)
+
+Finds records by 3-month quarterly period of year. Quarter numbering starts at 1. The four quarters of the year begin on Jan 1, Apr 1, Jul 1, and Oct 1 respectively.
+
+To find records from the current quarter:
+
+ Post.by_quarter
+
+To find records based on a quarter, you can pass in a number (representing the quarter number) or a time object:
+
+ Post.by_quarter(4)
+
+This will return all posts in the 4th quarter of the current year.
+
+ Post.by_quarter(2, :year => 2012)
+
+This will return all posts in the 2nd quarter of 2012.
+
+ Post.by_week(Time.local(2012,1,1))
+
+This will return all posts from the first quarter of 2012.
+
## Tomorrow (`tomorrow`)
*This method has been shown to be shifty when passed a `Date` object, it is recommended that you pass it an `ActiveSupport::TimeWithZone` object instead.*
@@ -238,7 +280,7 @@ You can also pass a string:
Post.after("next tuesday")
-## Between (`between`)
+## Between (`between` or `between_times`)
To find records between two times:
@@ -248,6 +290,10 @@ Also works with dates:
Post.between(date1, date2)
+`between_times` is an alias for `between`:
+
+ Post.between_times(time1, time2) #=> results identical to above
+
## Previous (`previous`)
To find the record prior to this one call `previous` on any model instance:
@@ -282,6 +328,10 @@ Or if you're doing it all the time on your model, then it's best to use `by_star
by_star_field :something_else
end
+## Mongoid
+
+Mongoid is only tested/supported on version 3.0+
+
## Collaborators
Thanks to Thomas Sinclair for the original bump for implementing it. I would like to thank #rubyonrails for their support and the following people:
View
1  by_star.gemspec
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "mysql2"
s.add_development_dependency "rspec-rails", "~> 2.8"
s.add_development_dependency "timecop", "~> 0.3"
+ s.add_development_dependency "mongoid", "~> 3.0" if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
s.add_dependency "activerecord", "~> 3.0"
s.add_dependency "chronic"
View
14 lib/by_star.rb
@@ -10,6 +10,7 @@
require 'by_star/by_week'
require 'by_star/by_weekend'
require 'by_star/by_day'
+require 'by_star/by_quarter'
module ByStar
@@ -25,6 +26,7 @@ def by_star_field(field=nil)
include ByWeek
include ByWeekend
include ByDay
+ include ByQuarter
class ParseError < StandardError
@@ -40,6 +42,7 @@ def between(start, finish, options={})
scope = scope.order(options[:order]) if options[:order]
scope
end
+ alias_method :between_times, :between
private
@@ -57,7 +60,12 @@ def time_klass(time)
end
-ActiveRecord::Base.send :extend, ByStar
-ActiveRecord::Relation.send :extend, ByStar
+if defined?(ActiveRecord)
+ ActiveRecord::Base.send :extend, ByStar
+ ActiveRecord::Relation.send :extend, ByStar
+ ActiveRecord::Base.send :include, ByStar::InstanceMethods
+end
-ActiveRecord::Base.send :include, ByStar::InstanceMethods
+if defined?(Mongoid)
+ require 'mongoid/by_star'
+end
View
4 lib/by_star/by_fortnight.rb
@@ -23,6 +23,10 @@ def by_fortnight_Time(time, options={})
between(start_time, (start_time + 2.weeks).end_of_day, options)
end
+ def by_fortnight_Date(date, options={})
+ by_fortnight_Time(date.to_time, options)
+ end
+
def by_fortnight_String_or_Fixnum(weeks, options={})
weeks = weeks.to_i
current_time = Time.zone.local(options[:year] || Time.zone.now.year)
View
24 lib/by_star/by_month.rb
@@ -6,20 +6,34 @@ module ByMonth
def by_month(*args)
options = args.extract_options!
time = args.first || Time.zone.now
- send("by_month_#{time_klass(time)}", time, options)
+ send("by_month_#{time_klass(time)}", time, false, options)
+ end
+
+ def by_calendar_month(*args)
+ options = args.extract_options!
+ time = args.first || Time.zone.now
+ send("by_month_#{time_klass(time)}", time, true, options)
end
private
- def by_month_Time(time, options={})
- between(time.beginning_of_month, time.end_of_month, options)
+ def by_month_Time(time, is_calendar=false, options={})
+ if is_calendar
+ between(time.beginning_of_month.beginning_of_week, time.end_of_month.end_of_week, options)
+ else
+ between(time.beginning_of_month, time.end_of_month, options)
+ end
+ end
+
+ def by_month_Date(date, is_calendar=false, options={})
+ by_month_Time(date.to_time, is_calendar, options)
end
- def by_month_String_or_Fixnum(month, options={})
+ def by_month_String_or_Fixnum(month, is_calendar=false, options={})
begin
year = options[:year] || Time.zone.now.year
date = Date.parse("#{year}-#{month}-01").to_time
- by_month_Time(date, options)
+ by_month_Time(date, is_calendar, options)
rescue
raise ParseError, "Month must be a number between 1 and 12 or the full month name (e.g. 'January', 'Feburary', etc.)"
View
32 lib/by_star/by_quarter.rb
@@ -0,0 +1,32 @@
+module ByStar
+ module ByQuarter
+ # For reasoning why I use *args rather than variables here,
+ # please see the by_year method comments in lib/by_star/by_year.rb
+
+ def by_quarter(*args)
+ options = args.extract_options!.symbolize_keys!
+ time = args.first
+ time ||= Time.zone.local(options[:year], 1, 1) if options[:year]
+ time ||= Time.zone.now
+ send("by_quarter_#{time_klass(time)}", time, options)
+ end
+
+ private
+
+ def by_quarter_Time(time, options={})
+ between(time.beginning_of_quarter, time.end_of_quarter, options)
+ end
+
+ def by_quarter_Date(date, options={})
+ by_quarter_Time(date.to_time, options)
+ end
+
+ def by_quarter_Fixnum(quarter, options={})
+ raise 'Quarter must be a number between 1 and 4' unless quarter >= 1 && quarter <= 4
+ time = Time.zone.local(options[:year], 1, 1) if options[:year]
+ time ||= Time.zone.now
+ start_time = time.beginning_of_year + ((quarter.to_i - 1) * 3).months
+ between(start_time, start_time.end_of_quarter, options)
+ end
+ end
+end
View
8 lib/by_star/by_week.rb
@@ -14,11 +14,13 @@ def by_week(*args)
private
- def by_week_Time_or_Date(time, options={})
+ def by_week_Time(time, options={})
between(time.beginning_of_week, time.end_of_week, options)
end
- alias_method :by_week_Time, :by_week_Time_or_Date
- alias_method :by_week_Date, :by_week_Time_or_Date
+
+ def by_week_Date(date, options={})
+ by_week_Time(date.to_time, options)
+ end
def by_week_Fixnum(week, options={})
time = Time.zone.local(options[:year], 1, 1) if options[:year]
View
3  lib/by_star/by_weekend.rb
@@ -13,5 +13,8 @@ def by_weekend_Time(time, options={})
between(time.beginning_of_weekend, time.end_of_weekend)
end
+ def by_weekend_Date(date, options={})
+ by_weekend_Time(date.to_time, options)
+ end
end
end
View
8 lib/by_star/by_year.rb
@@ -30,11 +30,13 @@ def by_year(*args)
private
- def by_year_Time_or_Date(time, options={})
+ def by_year_Time(time, options={})
between(time.beginning_of_year, time.end_of_year, options)
end
- alias_method :by_year_Time, :by_year_Time_or_Date
- alias_method :by_year_Date, :by_year_Time_or_Date
+
+ def by_year_Date(date, options={})
+ by_year_Time(date.to_time, options)
+ end
def by_year_String_or_Fixnum(year, options={})
by_year_Time("#{work_out_year(year)}-01-01".to_time, options)
View
2  lib/by_star/version.rb
@@ -1,3 +1,3 @@
module ByStar
- VERSION = "2.0.0.beta1"
+ VERSION = "2.1.0.beta1"
end
View
83 lib/mongoid/by_star.rb
@@ -0,0 +1,83 @@
+module Mongoid::ByStar
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ include ByStar
+
+ def by_star_field(field=nil)
+ @by_star_field ||= field
+ @by_star_field || :created_at
+ end
+
+ # override ByStar method
+ def between(start, finish, options={})
+ field = by_star_field_class(options)
+ scope = gte(field => start).lte(field => finish)
+ scope = scope.order_by(field => options[:order]) if options[:order]
+ scope
+ end
+ alias_method :between_times, :between
+
+ # override private methods in ByStar::ByDirection
+ def before_Time_or_Date(time_or_date, options={})
+ field = by_star_field_class(options)
+ lte(field => time_or_date)
+ end
+ alias_method :before_Time, :before_Time_or_Date
+ alias_method :before_Date, :before_Time_or_Date
+
+ def before_String(string, options={})
+ field = by_star_field_class(options)
+ if time = Chronic.parse(string)
+ lte(field => time)
+ else
+ raise ParseError, "Chronic couldn't understand #{string.inspect}. Please try something else."
+ end
+ end
+
+ def after_Time_or_Date(time_or_date, options={})
+ field = by_star_field_class(options)
+ gte(field => time_or_date)
+ end
+ alias_method :after_Time, :after_Time_or_Date
+ alias_method :after_Date, :after_Time_or_Date
+
+ def after_String(string, options={})
+ field = by_star_field_class(options)
+ if time = Chronic.parse(string)
+ gte(field => time)
+ else
+ raise ParseError, "Chronic couldn't understand #{string.inspect}. Please try something else."
+ end
+ end
+
+ protected
+
+ def by_star_field_class(options={})
+ field = options[:field] || by_star_field
+ field = aliased_fields[field.to_s] if aliased_fields.has_key?(field.to_s)
+ field.to_sym
+ end
+ end
+
+ include ByStar::InstanceMethods
+
+ # override ByStar::InstanceMethods methods
+ def previous(options={})
+ field = by_star_field_instance(options)
+ self.class.lt(field => self.send(field)).desc(field).first
+ end
+
+ def next(options={})
+ field = by_star_field_instance(options)
+ self.class.gt(field => self.send(field)).asc(field).first
+ end
+
+ protected
+
+ def by_star_field_instance(options={})
+ field = options[:field] || self.class.by_star_field
+ field = self.class.aliased_fields[field.to_s] if self.class.aliased_fields.has_key?(field.to_s)
+ field.to_sym
+ end
+end
View
50 spec/by_star/active_record/active_record_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+Dir[File.dirname(__FILE__) + '/../shared/*.rb'].each {|file| require file }
+
+describe ActiveRecord do
+ before(:all) do
+ ActiveRecord::Base.default_timezone = :utc
+
+ db_config = YAML::load_file(File.dirname(__FILE__) + "/../../database.yml")
+ if db_config.has_key?('sqlite') && db_config['sqlite'].has_key?('database')
+ db_config['sqlite']['database'] = File.dirname(__FILE__) + '/../../tmp/' + db_config['sqlite']['database']
+ end
+
+ ActiveRecord::Base.configurations = db_config
+ ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite")
+ load File.dirname(__FILE__) + "/../../fixtures/active_record/schema.rb"
+ load File.dirname(__FILE__) + "/../../fixtures/active_record/models.rb"
+ load File.dirname(__FILE__) + "/../../fixtures/shared/seeds.rb"
+
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/../../tmp/activerecord.log")
+ end
+
+ it_behaves_like "by day"
+ it_behaves_like "by direction"
+ it_behaves_like "by fortnight"
+ it_behaves_like "by month"
+ it_behaves_like "by quarter"
+ it_behaves_like "by week"
+ it_behaves_like "by weekend"
+ it_behaves_like "by year"
+
+ it "should be able to order the result set" do
+ scope = Post.by_year(Time.zone.now.year, :order => "created_at DESC")
+ scope.order_values.should == ["created_at DESC"]
+ end
+
+ describe "#between" do
+ it "should return an ActiveRecord::Relation object" do
+ Post.between(Date.today - 2, Date.today).class.should == ActiveRecord::Relation
+ end
+ it "should return a result set between two times" do
+ Post.between(Date.today - 2, Date.today).count.should == 1
+ end
+ end
+
+ describe "#between_times" do
+ it "should be an alias of #between" do
+ Post.between_times(Date.today - 2, Date.today).should == Post.between(Date.today - 2, Date.today)
+ end
+ end
+end
View
60 spec/by_star/by_day_spec.rb
@@ -1,60 +0,0 @@
-require 'spec_helper'
-
-describe "by day" do
- def posts_count(*args)
- Post.by_day(*args).count
- end
-
- it "should be able to find a post for today" do
- posts_count.should eql(4)
- end
-
- it "should be able to find a post by a given date in last year" do
- posts_count(:year => Time.zone.now.year - 1).should eql(1)
- end
-
- it "should be able to use an alternative field" do
- Event.by_day(Time.now.yesterday, :field => "start_time").size.should eql(1)
- end
-
- it "should be able to use a date" do
- posts_count(Date.today).should eql(4)
- end
-
- it "should be able to use a String" do
- posts_count(Date.today.to_s).should eql(4)
- end
-end
-
-describe "today" do
- it "should show the post for today" do
- Post.today.map(&:text).should include("Today's post")
- end
-
- it "should be able to use an alternative field" do
- # Test may occur on an event day.
- Event.today(:field => "start_time").size.should eql(1)
- end
-end
-
-describe "yesterday" do
-
- it "should show the post for yesterday" do
- Post.yesterday.map(&:text).should include("Yesterday's post")
- end
-
- it "should be able to use an alternative field" do
- Event.yesterday(:field => "start_time").size.should eql(1)
- end
-
-end
-
-describe "tomorrow" do
- it "should show the post for tomorrow" do
- Post.tomorrow.map(&:text).should include("Tomorrow's post")
- end
-
- it "should be able to use an alternative field" do
- Event.tomorrow(:field => "start_time").size.should eql(1)
- end
-end
View
82 spec/by_star/by_direction_spec.rb
@@ -1,82 +0,0 @@
-require 'spec_helper'
-describe "before" do
- def posts_count(*args)
- Post.before(*args).count
- end
-
- it "should show the correct number of posts in the past" do
- posts_count.should == 5
- end
-
- it "is aliased as before_now" do
- Post.before_now.count.should == 5
- end
-
- it "should find for a given time" do
- posts_count(Time.zone.now - 2.days).should eql(2)
- end
-
- it "should find for a given date" do
- posts_count(Date.today - 2).should eql(2)
- end
-
- it "should find for a given string" do
- posts_count("next tuesday").should eql(8)
- end
-
- it "raises an exception when Chronic can't parse" do
- lambda { posts_count(";aosdjbjisdabdgofbi") }.should raise_error(ByStar::ParseError)
- end
-
- it "should be able to find all events before Ryan's birthday using a non-standard field" do
- Event.before(Time.local(Time.zone.now.year+2), :field => "start_time").count.should eql(8)
- end
-end
-
-describe "future" do
- def posts_count(*args)
- Post.after(*args).count
- end
-
- it "should show the correct number of posts in the future" do
- Post.after.count.should eql(posts_count)
- Post.after_now.count.should eql(posts_count)
- end
-
- it "should find for a given date" do
- posts_count(Date.today - 2).should eql(19)
- end
-
- it "should find for a given string" do
- posts_count("next tuesday").should eql(13)
- end
-
- it "should be able to find all events before Dad's birthday using a non-standard field" do
- Event.after(Time.zone.local(Time.zone.now.year, 7, 5), :field => "start_time").count.should eql(3)
- end
-end
-
-describe "previous and next" do
- let(:current_post) { Post.find_by_text("post 1") }
- let(:current_event) { Event.find_by_name("Mum's birthday!") }
-
- context "previous" do
- it "can find the previous post" do
- current_post.previous.text.should == "Yesterday's post"
- end
-
- it "takes the field option" do
- current_event.previous(:field => "start_time").name.should == "Dad's birthday!"
- end
- end
-
- context "next" do
- it "can find the next post" do
- current_post.next.text.should == "Today's post"
- end
-
- it "takes the field option" do
- current_event.next(:field => "start_time").name.should == "Ryan's birthday!"
- end
- end
-end
View
46 spec/by_star/by_fortnight_spec.rb
@@ -1,46 +0,0 @@
-require 'spec_helper'
-
-describe "by fortnight" do
-
- def find_posts(*args)
- Post.by_fortnight(*args)
- end
-
- def posts_count(*args)
- find_posts(*args).count
- end
-
- it "should be able to find posts in the current fortnight" do
- posts_count.should eql(6)
- end
-
- it "should be able to find posts in the 1st fortnight of the current year" do
- posts_count(0).should eql(6)
- posts_count("0").should eql(6)
- # There was previously a situation where incorrect time zone math
- # caused the 'post 1' post to NOT appear, so count would be 7, rather than 8.
- # So this line simply regression tests that problem.
- Post.by_fortnight(0).map(&:text).should include("post 1")
- end
-
- it "should be able to find posts for a fortnight ago" do
- posts_count(2.weeks.ago).should eql(2)
- end
-
- it "should be able to find posts for a given fortnight in a year" do
- posts_count(0, :year => Time.zone.now.year - 1).should eql(1)
- end
-
- it "should be able to find posts for the current fortnight in a specific year" do
- posts_count(:year => Time.zone.now.year - 1).should eql(1)
- end
-
- it "should raise an error when given an invalid argument" do
- lambda { find_posts(27) }.should raise_error(ByStar::ParseError, "by_fortnight takes only a Time, Date or a Fixnum (less than or equal to 26).")
- end
-
- it "should be able to use an alternative field" do
- Event.by_fortnight(nil, :field => "start_time").count.should eql(2)
- end
-end
-
View
60 spec/by_star/by_month_spec.rb
@@ -1,60 +0,0 @@
-require 'spec_helper'
-
-describe "by_month" do
- def find_posts(time=Time.zone.now, options={})
- Post.by_month(time, options)
- end
-
- def posts_count(time=Time.zone.now, options={})
- find_posts(time, options).count
- end
-
- it "should be able to find posts for the current month" do
- posts_count.should eql(6)
- end
-
- it "should be able to find a single post for January" do
- # If it is January we'll have all the "current" posts in there.
- # This makes the count 10.
- # I'm sure you can guess what happens when it's not January.
- posts_count("January").should eql(6)
- end
-
- it "should be able to find two posts for the 2nd month" do
- # If it is February we'll have all the "current" posts in there.
- # This makes the count 10.
- # I'm sure you can guess what happens when it's not February.
- posts_count(2).should eql(1)
- end
-
- it "should be able to find three posts for the 3rd month, using time instance" do
- # If it is March we'll have all the "current" posts in there.
- # This makes the count 10.
- # I'm sure you can guess what happens when it's not March.
- time = Time.local(Time.zone.now.year, 3, 1)
- posts_count(time).should eql(1)
- end
-
- it "should be able to find a single post from January last year" do
- posts_count("January", :year => Time.zone.now.year - 1).should eql(1)
- end
-
- it "should fail when given incorrect months" do
- lambda { find_posts(0) }.should raise_error(ByStar::ParseError)
- lambda { find_posts(13) }.should raise_error(ByStar::ParseError)
- lambda { find_posts("Ryan") }.should raise_error(ByStar::ParseError)
- # LOL arrays
- lambda { find_posts([1,2,3]) }.should raise_error(NoMethodError)
- end
-
- it "should be able to use an alternative field" do
- Timecop.freeze(Time.zone.local(Time.zone.now.year, 12, 1, 0, 0, 0)) do
- Event.by_month(:field => "start_time").size.should eql(1)
- end
- end
-
- it "should be able to specify the year as a string" do
- posts_count(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
- end
-
-end
View
39 spec/by_star/by_week_spec.rb
@@ -1,39 +0,0 @@
-require 'spec_helper'
-describe "by week" do
- def posts_count(*args)
- find_posts(*args).count
- end
-
- def find_posts(*args)
- Post.by_week(*args)
- end
-
- it "should be able to find posts in the current week" do
- posts_count.should eql(5)
- end
-
- it "should be able to find posts in the 1st week" do
- posts_count(0).should eql(6)
- end
-
- it "should be able to find posts in the 1st week of last year" do
- posts_count(0, :year => Time.zone.now.year-1).should eql(1)
- end
-
- it "should not find any posts from a week ago" do
- posts_count(1.week.ago).should eql(1)
- end
-
- it "should be able to use an alternative field" do
- Event.by_week(:field => "start_time").size.should eql(2)
- end
-
- it "should find posts at the start of the year" do
- posts_count(0).should eql(6)
- end
-
- it "should find posts at the end of the year" do
- posts_count(Time.zone.now.end_of_year).should eql(1)
- end
-
-end
View
12 spec/by_star/by_weekend_spec.rb
@@ -1,12 +0,0 @@
-require 'spec_helper'
-
-describe 'by weekend' do
-
- it "should be able to find the posts on the weekend of the 1st of January" do
- Post.by_weekend.count.should eql(6)
- end
-
- it "should be able to use an alternative field" do
- Event.by_weekend(:field => "start_time").count.should eql(3)
- end
-end
View
57 spec/by_star/by_year_spec.rb
@@ -1,57 +0,0 @@
-require 'spec_helper'
-
-describe "by_year" do
- def posts_count(*args)
- find_posts(*args).count
- end
-
- def find_posts(*args)
- options = args.extract_options!
- Post.by_year(args.first, options)
- end
-
- let(:this_years_posts) { 18 }
-
- it "should be able to find all the posts in the current year" do
- posts_count.should eql(this_years_posts)
- end
-
- it "should be able to find if given a string" do
- posts_count(Time.zone.now.year.to_s).should eql(this_years_posts)
- end
-
- it "should be able to find a single post from last year" do
- posts_count(Time.zone.now.year-1).should eql(3)
- end
-
- it "knows what last year's posts were" do
- find_posts(Time.zone.now.year-1).map(&:text).should =~ ["A week ago", "This time, last year", "Yesterday's post"]
- end
-
- it "can find posts given a 2-digit year" do
- # Should be good for at least a couple of years.
- posts_count(Time.zone.now.year-2001).should eql(3)
- end
-
- it "should be able to use an alternative field (string)" do
- Event.by_year(:field => "start_time").count.should eql(6)
- end
-
- it "should be able to use an alternative field (symbol)" do
- Event.by_year(:field => :start_time).count.should eql(6)
- end
-
- it "should not have to specify the field when using by_star_field" do
- Event.by_year.count.should eql(6)
- end
-
- it "should not include yesterday's (Dec 31st <last year>) event in by_year" do
- Event.by_year.map(&:name).should_not include("Yesterday")
- end
-
- it "should be able to order the result set" do
- scope = find_posts(Time.zone.now.year, :order => "created_at DESC")
- scope.order_values.should == ["created_at DESC"]
- end
-end
-
View
44 spec/by_star/mongoid/mongoid_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+Dir[File.dirname(__FILE__) + '/../shared/*.rb'].each {|file| require file }
+
+describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3') do
+
+ before(:all) do
+ DATABASE_NAME = "mongoid_#{Process.pid}"
+
+ Mongoid.configure do |config|
+ config.connect_to DATABASE_NAME
+ end
+
+ load File.dirname(__FILE__) + "/../../fixtures/mongoid/models.rb"
+ load File.dirname(__FILE__) + "/../../fixtures/shared/seeds.rb"
+ end
+
+ after(:all) do
+ Mongoid.purge!
+ end
+
+ it_behaves_like "by day"
+ it_behaves_like "by direction"
+ it_behaves_like "by fortnight"
+ it_behaves_like "by month"
+ it_behaves_like "by quarter"
+ it_behaves_like "by week"
+ it_behaves_like "by weekend"
+ it_behaves_like "by year"
+
+ describe "#between" do
+ it "should return a Mongoid::Critera object" do
+ Post.between(Date.today - 2, Date.today).class.should == Mongoid::Criteria
+ end
+ it "should return a result set between two times" do
+ Post.between(Date.today - 2, Date.today).count.should == 1
+ end
+ end
+
+ describe "#between_times" do
+ it "should be an alias of #between" do
+ Post.between_times(Date.today - 2, Date.today).should == Post.between(Date.today - 2, Date.today)
+ end
+ end
+end
View
62 spec/by_star/shared/by_day.rb
@@ -0,0 +1,62 @@
+require 'spec_helper'
+
+shared_examples_for "by day" do
+ describe "by day" do
+ def posts_count(*args)
+ Post.by_day(*args).count
+ end
+
+ it "should be able to find a post for today" do
+ posts_count.should eql(4)
+ end
+
+ it "should be able to find a post by a given date in last year" do
+ posts_count(:year => Time.zone.now.year - 1).should eql(1)
+ end
+
+ it "should be able to use an alternative field" do
+ Event.by_day(Time.now.yesterday, :field => "start_time").size.should eql(1)
+ end
+
+ it "should be able to use a date" do
+ posts_count(Date.today).should eql(4)
+ end
+
+ it "should be able to use a String" do
+ posts_count(Date.today.to_s).should eql(4)
+ end
+ end
+
+ describe "today" do
+ it "should show the post for today" do
+ Post.today.map(&:text).should include("Today's post")
+ end
+
+ it "should be able to use an alternative field" do
+ # Test may occur on an event day.
+ Event.today(:field => "start_time").size.should eql(1)
+ end
+ end
+
+ describe "yesterday" do
+
+ it "should show the post for yesterday" do
+ Post.yesterday.map(&:text).should include("Yesterday's post")
+ end
+
+ it "should be able to use an alternative field" do
+ Event.yesterday(:field => "start_time").size.should eql(1)
+ end
+
+ end
+
+ describe "tomorrow" do
+ it "should show the post for tomorrow" do
+ Post.tomorrow.map(&:text).should include("Tomorrow's post")
+ end
+
+ it "should be able to use an alternative field" do
+ Event.tomorrow(:field => "start_time").size.should eql(1)
+ end
+ end
+end
View
85 spec/by_star/shared/by_direction.rb
@@ -0,0 +1,85 @@
+require 'spec_helper'
+
+shared_examples_for "by direction" do
+ describe "before" do
+ def posts_count(*args)
+ Post.before(*args).count
+ end
+
+ it "should show the correct number of posts in the past" do
+ posts_count.should == 5
+ end
+
+ it "is aliased as before_now" do
+ Post.before_now.count.should == 5
+ end
+
+ it "should find for a given time" do
+ posts_count(Time.zone.now - 2.days).should eql(2)
+ end
+
+ it "should find for a given date" do
+ posts_count(Date.today - 2).should eql(2)
+ end
+
+ it "should find for a given string" do
+ posts_count("next tuesday").should eql(8)
+ end
+
+ it "raises an exception when Chronic can't parse" do
+ lambda { posts_count(";aosdjbjisdabdgofbi") }.should raise_error(ByStar::ParseError)
+ end
+
+ it "should be able to find all events before Ryan's birthday using a non-standard field" do
+ Event.before(Time.local(Time.zone.now.year+2), :field => "start_time").count.should eql(8)
+ end
+ end
+
+ describe "future" do
+ def posts_count(*args)
+ Post.after(*args).count
+ end
+
+ it "should show the correct number of posts in the future" do
+ Post.after.count.should eql(posts_count)
+ Post.after_now.count.should eql(posts_count)
+ end
+
+ it "should find for a given date" do
+ posts_count(Date.today - 2).should eql(19)
+ end
+
+ it "should find for a given string" do
+ posts_count("next tuesday").should eql(13)
+ end
+
+ it "should be able to find all events before Dad's birthday using a non-standard field" do
+ Event.after(Time.zone.local(Time.zone.now.year, 7, 5), :field => "start_time").count.should eql(3)
+ end
+ end
+
+ describe "previous and next" do
+ let(:current_post) { Post.find_by_text("post 1") }
+ let(:current_event) { Event.find_by_name("Mum's birthday!") }
+
+ context "previous" do
+ it "can find the previous post" do
+ current_post.previous.text.should == "Yesterday's post"
+ end
+
+ it "takes the field option" do
+ current_event.previous(:field => "start_time").name.should == "Dad's birthday!"
+ end
+ end
+
+ context "next" do
+ it "can find the next post" do
+ current_post.next.text.should == "Today's post"
+ end
+
+ it "takes the field option" do
+ current_event.next(:field => "start_time").name.should == "Ryan's birthday!"
+ end
+ end
+ end
+end
View
47 spec/by_star/shared/by_fortnight.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+shared_examples_for "by fortnight" do
+ describe "by fortnight" do
+ def find_posts(*args)
+ Post.by_fortnight(*args)
+ end
+
+ def posts_count(*args)
+ find_posts(*args).count
+ end
+
+ it "should be able to find posts in the current fortnight" do
+ posts_count.should eql(6)
+ end
+
+ it "should be able to find posts in the 1st fortnight of the current year" do
+ posts_count(0).should eql(6)
+ posts_count("0").should eql(6)
+ # There was previously a situation where incorrect time zone math
+ # caused the 'post 1' post to NOT appear, so count would be 7, rather than 8.
+ # So this line simply regression tests that problem.
+ Post.by_fortnight(0).map(&:text).should include("post 1")
+ end
+
+ it "should be able to find posts for a fortnight ago" do
+ posts_count(2.weeks.ago).should eql(2)
+ end
+
+ it "should be able to find posts for a given fortnight in a year" do
+ posts_count(0, :year => Time.zone.now.year - 1).should eql(1)
+ end
+
+ it "should be able to find posts for the current fortnight in a specific year" do
+ posts_count(:year => Time.zone.now.year - 1).should eql(1)
+ end
+
+ it "should raise an error when given an invalid argument" do
+ lambda { find_posts(27) }.should raise_error(ByStar::ParseError, "by_fortnight takes only a Time, Date or a Fixnum (less than or equal to 26).")
+ end
+
+ it "should be able to use an alternative field" do
+ Event.by_fortnight(nil, :field => "start_time").count.should eql(2)
+ end
+ end
+end
+
View
109 spec/by_star/shared/by_month.rb
@@ -0,0 +1,109 @@
+require 'spec_helper'
+
+shared_examples_for "by month" do
+ describe "by month" do
+ def find_posts(time=Time.zone.now, options={})
+ Post.by_month(time, options)
+ end
+
+ def posts_count(time=Time.zone.now, options={})
+ find_posts(time, options).count
+ end
+
+ it "should be able to find posts for the current month" do
+ posts_count.should eql(6)
+ end
+
+ it "should be able to find a single post for January" do
+ # If it is January we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not January.
+ posts_count("January").should eql(6)
+ end
+
+ it "should be able to find two posts for the 2nd month" do
+ # If it is February we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not February.
+ posts_count(2).should eql(1)
+ end
+
+ it "should be able to find three posts for the 3rd month, using time instance" do
+ # If it is March we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not March.
+ time = Time.local(Time.zone.now.year, 3, 1)
+ posts_count(time).should eql(1)
+ end
+
+ it "should be able to find a single post from January last year" do
+ posts_count("January", :year => Time.zone.now.year - 1).should eql(1)
+ end
+
+ it "should fail when given incorrect months" do
+ lambda { find_posts(0) }.should raise_error(ByStar::ParseError)
+ lambda { find_posts(13) }.should raise_error(ByStar::ParseError)
+ lambda { find_posts("Ryan") }.should raise_error(ByStar::ParseError)
+ # LOL arrays
+ lambda { find_posts([1,2,3]) }.should raise_error(NoMethodError)
+ end
+
+ it "should be able to use an alternative field" do
+ Timecop.freeze(Time.zone.local(Time.zone.now.year, 12, 1, 0, 0, 0)) do
+ Event.by_month(:field => "start_time").size.should eql(1)
+ end
+ end
+
+ it "should be able to specify the year as a string" do
+ posts_count(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
+ end
+
+ it "should be able to accept time datatype" do
+ posts_count(Time.now - 1.year).should eql(1)
+ end
+
+ it "should be able to accept date datatype" do
+ posts_count(Date.today - 1.year).should eql(1)
+ end
+ end
+
+ describe "by calendar month" do
+ def find_posts(time=Time.zone.now, options={})
+ Post.by_calendar_month(time, options)
+ end
+
+ def posts_count(time=Time.zone.now, options={})
+ find_posts(time, options).count
+ end
+
+ it "should be able to find posts for the current calendar month" do
+ posts_count.should eql(8)
+ end
+
+ it "should be able to find a single post for January calendar month" do
+ # If it is January we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not January.
+ posts_count("January").should eql(8)
+ end
+
+ it "should be able to find two posts for the 2nd calendar month" do
+ # If it is February we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not February.
+ posts_count(2).should eql(2)
+ end
+
+ it "should be able to find three posts for the 3rd calendar month, using time instance" do
+ # If it is March we'll have all the "current" posts in there.
+ # This makes the count 10.
+ # I'm sure you can guess what happens when it's not March.
+ time = Time.local(Time.zone.now.year, 3, 1)
+ posts_count(time).should eql(1)
+ end
+
+ it "should be able to find a single post from January last year" do
+ posts_count("January", :year => Time.zone.now.year - 1).should eql(1)
+ end
+ end
+end
View
33 spec/by_star/shared/by_quarter.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+shared_examples_for "by quarter" do
+ describe "by quarter" do
+ def posts_count(*args)
+ find_posts(*args).count
+ end
+
+ def find_posts(*args)
+ Post.by_quarter(*args)
+ end
+
+ it "should be able to find posts in the current quarter" do
+ posts_count.should eql(8)
+ end
+
+ it "should be able to find posts in the 1st quarter" do
+ posts_count(1).should eql(8)
+ end
+
+ it "should be able to find posts in the 1st quarter of last year" do
+ posts_count(1, :year => Time.zone.now.year-1).should eql(1)
+ end
+
+ it "should be able to use an alternative field" do
+ Event.by_quarter(:field => "start_time").size.should eql(3)
+ end
+
+ it "should find posts at the last quarter of the year" do
+ posts_count(Time.zone.now.end_of_year).should eql(4)
+ end
+ end
+end
View
41 spec/by_star/shared/by_week.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+shared_examples_for "by week" do
+ describe "by week" do
+ def posts_count(*args)
+ find_posts(*args).count
+ end
+
+ def find_posts(*args)
+ Post.by_week(*args)
+ end
+
+ it "should be able to find posts in the current week" do
+ posts_count.should eql(5)
+ end
+
+ it "should be able to find posts in the 1st week" do
+ posts_count(0).should eql(6)
+ end
+
+ it "should be able to find posts in the 1st week of last year" do
+ posts_count(0, :year => Time.zone.now.year-1).should eql(1)
+ end
+
+ it "should not find any posts from a week ago" do
+ posts_count(1.week.ago).should eql(1)
+ end
+
+ it "should be able to use an alternative field" do
+ Event.by_week(:field => "start_time").size.should eql(2)
+ end
+
+ it "should find posts at the start of the year" do
+ posts_count(0).should eql(6)
+ end
+
+ it "should find posts at the end of the year" do
+ posts_count(Time.zone.now.end_of_year).should eql(1)
+ end
+ end
+end
View
13 spec/by_star/shared/by_weekend.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+shared_examples_for "by weekend" do
+ describe "by weekend" do
+ it "should be able to find the posts on the weekend of the 1st of January" do
+ Post.by_weekend.count.should eql(6)
+ end
+
+ it "should be able to use an alternative field" do
+ Event.by_weekend(:field => "start_time").count.should eql(3)
+ end
+ end
+end
View
54 spec/by_star/shared/by_year.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+shared_examples_for "by year" do
+ describe "by year" do
+ def posts_count(*args)
+ find_posts(*args).count
+ end
+
+ def find_posts(*args)
+ options = args.extract_options!
+ Post.by_year(args.first, options)
+ end
+
+ let(:this_years_posts) { 18 }
+
+ it "should be able to find all the posts in the current year" do
+ posts_count.should eql(this_years_posts)
+ end
+
+ it "should be able to find if given a string" do
+ posts_count(Time.zone.now.year.to_s).should eql(this_years_posts)
+ end
+
+ it "should be able to find a single post from last year" do
+ posts_count(Time.zone.now.year-1).should eql(3)
+ end
+
+ it "knows what last year's posts were" do
+ find_posts(Time.zone.now.year-1).map(&:text).should =~ ["A week ago", "This time, last year", "Yesterday's post"]
+ end
+
+ it "can find posts given a 2-digit year" do
+ # Should be good for at least a couple of years.
+ posts_count(Time.zone.now.year-2001).should eql(3)
+ end
+
+ it "should be able to use an alternative field (string)" do
+ Event.by_year(:field => "start_time").count.should eql(6)
+ end
+
+ it "should be able to use an alternative field (symbol)" do
+ Event.by_year(:field => :start_time).count.should eql(6)
+ end
+
+ it "should not have to specify the field when using by_star_field" do
+ Event.by_year.count.should eql(6)
+ end
+
+ it "should not include yesterday's (Dec 31st <last year>) event in by_year" do
+ Event.by_year.map(&:name).should_not include("Yesterday")
+ end
+ end
+end
+
View
13 spec/fixtures/active_record/models.rb
@@ -0,0 +1,13 @@
+class Post < ActiveRecord::Base
+ default_scope :order => "#{quoted_table_name}.created_at ASC"
+ has_and_belongs_to_many :tags
+
+ def self.factory(text, created_at = nil)
+ create!(:text => text, :created_at => created_at)
+ end
+end
+
+class Event < ActiveRecord::Base
+ by_star_field :start_time
+ scope :secret, :conditions => { :public => false }
+end
View
0  spec/fixtures/schema.rb → spec/fixtures/active_record/schema.rb
File renamed without changes
View
65 spec/fixtures/mongoid/models.rb
@@ -0,0 +1,65 @@
+class Post
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ include Mongoid::ByStar
+
+ field :text, type: String
+
+ default_scope order_by([[:created_at, :asc]])
+ has_and_belongs_to_many :tags
+
+ def self.factory(text, created_at = nil)
+ create!(:text => text, :created_at => created_at)
+ end
+
+ def self.find_by_text(text)
+ where(:text => text).first
+ end
+end
+
+class Event
+ include Mongoid::Document
+ include Mongoid::ByStar
+
+ field :st, as: :start_time, type: DateTime
+ field :end_time, type: DateTime
+ field :name, type: String
+ field :public, type: Boolean, default: true
+
+ by_star_field :start_time
+ scope :secret, where(:public => false)
+
+ def self.find_by_name(name)
+ where(:name => name).first
+ end
+end
+
+class Tag
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ include Mongoid::ByStar
+
+ field :name, type: String
+
+ has_and_belongs_to_many :posts
+end
+
+class Invoice
+ include Mongoid::Document
+ include Mongoid::ByStar
+
+ field :value, type: Integer
+ field :number, type: Integer
+
+ has_many :day_entries
+end
+
+class DayEntry
+ include Mongoid::Document
+ include Mongoid::ByStar
+
+ field :spent_at, type: DateTime
+ field :name, type: String
+
+ belongs_to :invoice
+end
View
16 spec/fixtures/models.rb → spec/fixtures/shared/seeds.rb
@@ -1,19 +1,3 @@
-class Post < ActiveRecord::Base
- default_scope :order => "#{quoted_table_name}.created_at ASC"
- has_and_belongs_to_many :tags
-
- def self.factory(text, created_at = nil)
- create!(:text => text, :created_at => created_at)
- end
-end
-
-class Event < ActiveRecord::Base
- by_star_field :start_time
- scope :secret, :conditions => { :public => false }
-end
-
-## seed data:
-
year = Time.zone.now.year
1.upto(12) do |month|
View
15 spec/spec_helper.rb
@@ -1,32 +1,27 @@
require 'rubygems'
require 'bundler'
Bundler.setup
-require 'active_record'
require 'fileutils'
require 'logger'
-FileUtils.mkdir_p("tmp")
+FileUtils.mkdir_p(File.dirname(__FILE__) + "/tmp")
$:.unshift(File.join(File.dirname(__FILE__), "../lib"))
+require 'active_record'
+require 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
require 'active_support'
require 'active_support/core_ext/string/conversions'
require 'by_star'
require 'rspec'
require 'timecop'
+
# Define time zone before loading test_helper
zone = "UTC"
Time.zone = zone
-ActiveRecord::Base.default_timezone = :utc
-
-ActiveRecord::Base.configurations = YAML::load_file(File.dirname(__FILE__) + "/database.yml")
-ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite")
-load File.dirname(__FILE__) + "/fixtures/schema.rb"
# Freeze time to Jan 1st of this year
Timecop.travel(Time.zone.local(Time.zone.now.year, 1, 1, 0, 0, 1, 0))
-load File.dirname(__FILE__) + "/fixtures/models.rb"
-
# Print the location of puts/p calls so you can find them later
# def puts str
@@ -38,5 +33,3 @@
# puts caller.first
# super obj
# end
-
-ActiveRecord::Base.logger = Logger.new("tmp/activerecord.log")
Please sign in to comment.
Something went wrong with that request. Please try again.