by_star 2.0.0.beta1 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.travis.yml +2 -0
  2. data/Gemfile.lock +42 -42
  3. data/README.markdown +78 -14
  4. data/by_star.gemspec +3 -2
  5. data/lib/by_star.rb +12 -4
  6. data/lib/by_star/by_day.rb +4 -0
  7. data/lib/by_star/by_fortnight.rb +4 -0
  8. data/lib/by_star/by_month.rb +24 -12
  9. data/lib/by_star/by_quarter.rb +32 -0
  10. data/lib/by_star/by_week.rb +5 -3
  11. data/lib/by_star/by_weekend.rb +3 -0
  12. data/lib/by_star/by_year.rb +5 -3
  13. data/lib/by_star/version.rb +1 -1
  14. data/lib/mongoid/by_star.rb +83 -0
  15. data/spec/by_star/active_record/active_record_spec.rb +50 -0
  16. data/spec/by_star/mongoid/mongoid_spec.rb +44 -0
  17. data/spec/by_star/shared/by_day.rb +62 -0
  18. data/spec/by_star/shared/by_direction.rb +85 -0
  19. data/spec/by_star/shared/by_fortnight.rb +47 -0
  20. data/spec/by_star/shared/by_month.rb +109 -0
  21. data/spec/by_star/shared/by_quarter.rb +33 -0
  22. data/spec/by_star/shared/by_week.rb +41 -0
  23. data/spec/by_star/shared/by_weekend.rb +13 -0
  24. data/spec/by_star/shared/by_year.rb +54 -0
  25. data/spec/fixtures/active_record/models.rb +13 -0
  26. data/spec/fixtures/{schema.rb → active_record/schema.rb} +0 -0
  27. data/spec/fixtures/mongoid/models.rb +65 -0
  28. data/spec/fixtures/{models.rb → shared/seeds.rb} +0 -16
  29. data/spec/spec_helper.rb +4 -11
  30. metadata +95 -31
  31. data/spec/by_star/by_day_spec.rb +0 -52
  32. data/spec/by_star/by_direction_spec.rb +0 -82
  33. data/spec/by_star/by_fortnight_spec.rb +0 -46
  34. data/spec/by_star/by_month_spec.rb +0 -60
  35. data/spec/by_star/by_week_spec.rb +0 -39
  36. data/spec/by_star/by_weekend_spec.rb +0 -12
  37. data/spec/by_star/by_year_spec.rb +0 -57
@@ -14,11 +14,13 @@ module ByStar
14
14
 
15
15
  private
16
16
 
17
- def by_week_Time_or_Date(time, options={})
17
+ def by_week_Time(time, options={})
18
18
  between(time.beginning_of_week, time.end_of_week, options)
19
19
  end
20
- alias_method :by_week_Time, :by_week_Time_or_Date
21
- alias_method :by_week_Date, :by_week_Time_or_Date
20
+
21
+ def by_week_Date(date, options={})
22
+ by_week_Time(date.to_time, options)
23
+ end
22
24
 
23
25
  def by_week_Fixnum(week, options={})
24
26
  time = Time.zone.local(options[:year], 1, 1) if options[:year]
@@ -13,5 +13,8 @@ module ByStar
13
13
  between(time.beginning_of_weekend, time.end_of_weekend)
14
14
  end
15
15
 
16
+ def by_weekend_Date(date, options={})
17
+ by_weekend_Time(date.to_time, options)
18
+ end
16
19
  end
17
20
  end
@@ -30,11 +30,13 @@ module ByStar
30
30
 
31
31
  private
32
32
 
33
- def by_year_Time_or_Date(time, options={})
33
+ def by_year_Time(time, options={})
34
34
  between(time.beginning_of_year, time.end_of_year, options)
35
35
  end
36
- alias_method :by_year_Time, :by_year_Time_or_Date
37
- alias_method :by_year_Date, :by_year_Time_or_Date
36
+
37
+ def by_year_Date(date, options={})
38
+ by_year_Time(date.to_time, options)
39
+ end
38
40
 
39
41
  def by_year_String_or_Fixnum(year, options={})
40
42
  by_year_Time("#{work_out_year(year)}-01-01".to_time, options)
@@ -1,3 +1,3 @@
1
1
  module ByStar
2
- VERSION = "2.0.0.beta1"
2
+ VERSION = "2.1.0.beta2"
3
3
  end
@@ -0,0 +1,83 @@
1
+ module Mongoid::ByStar
2
+ extend ActiveSupport::Concern
3
+
4
+ module ClassMethods
5
+ include ByStar
6
+
7
+ def by_star_field(field=nil)
8
+ @by_star_field ||= field
9
+ @by_star_field || :created_at
10
+ end
11
+
12
+ # override ByStar method
13
+ def between(start, finish, options={})
14
+ field = by_star_field_class(options)
15
+ scope = gte(field => start).lte(field => finish)
16
+ scope = scope.order_by(field => options[:order]) if options[:order]
17
+ scope
18
+ end
19
+ alias_method :between_times, :between
20
+
21
+ # override private methods in ByStar::ByDirection
22
+ def before_Time_or_Date(time_or_date, options={})
23
+ field = by_star_field_class(options)
24
+ lte(field => time_or_date)
25
+ end
26
+ alias_method :before_Time, :before_Time_or_Date
27
+ alias_method :before_Date, :before_Time_or_Date
28
+
29
+ def before_String(string, options={})
30
+ field = by_star_field_class(options)
31
+ if time = Chronic.parse(string)
32
+ lte(field => time)
33
+ else
34
+ raise ParseError, "Chronic couldn't understand #{string.inspect}. Please try something else."
35
+ end
36
+ end
37
+
38
+ def after_Time_or_Date(time_or_date, options={})
39
+ field = by_star_field_class(options)
40
+ gte(field => time_or_date)
41
+ end
42
+ alias_method :after_Time, :after_Time_or_Date
43
+ alias_method :after_Date, :after_Time_or_Date
44
+
45
+ def after_String(string, options={})
46
+ field = by_star_field_class(options)
47
+ if time = Chronic.parse(string)
48
+ gte(field => time)
49
+ else
50
+ raise ParseError, "Chronic couldn't understand #{string.inspect}. Please try something else."
51
+ end
52
+ end
53
+
54
+ protected
55
+
56
+ def by_star_field_class(options={})
57
+ field = options[:field] || by_star_field
58
+ field = aliased_fields[field.to_s] if aliased_fields.has_key?(field.to_s)
59
+ field.to_sym
60
+ end
61
+ end
62
+
63
+ include ByStar::InstanceMethods
64
+
65
+ # override ByStar::InstanceMethods methods
66
+ def previous(options={})
67
+ field = by_star_field_instance(options)
68
+ self.class.lt(field => self.send(field)).desc(field).first
69
+ end
70
+
71
+ def next(options={})
72
+ field = by_star_field_instance(options)
73
+ self.class.gt(field => self.send(field)).asc(field).first
74
+ end
75
+
76
+ protected
77
+
78
+ def by_star_field_instance(options={})
79
+ field = options[:field] || self.class.by_star_field
80
+ field = self.class.aliased_fields[field.to_s] if self.class.aliased_fields.has_key?(field.to_s)
81
+ field.to_sym
82
+ end
83
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ Dir[File.dirname(__FILE__) + '/../shared/*.rb'].each {|file| require file }
3
+
4
+ describe ActiveRecord do
5
+ before(:all) do
6
+ ActiveRecord::Base.default_timezone = :utc
7
+
8
+ db_config = YAML::load_file(File.dirname(__FILE__) + "/../../database.yml")
9
+ if db_config.has_key?('sqlite') && db_config['sqlite'].has_key?('database')
10
+ db_config['sqlite']['database'] = File.dirname(__FILE__) + '/../../tmp/' + db_config['sqlite']['database']
11
+ end
12
+
13
+ ActiveRecord::Base.configurations = db_config
14
+ ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite")
15
+ load File.dirname(__FILE__) + "/../../fixtures/active_record/schema.rb"
16
+ load File.dirname(__FILE__) + "/../../fixtures/active_record/models.rb"
17
+ load File.dirname(__FILE__) + "/../../fixtures/shared/seeds.rb"
18
+
19
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/../../tmp/activerecord.log")
20
+ end
21
+
22
+ it_behaves_like "by day"
23
+ it_behaves_like "by direction"
24
+ it_behaves_like "by fortnight"
25
+ it_behaves_like "by month"
26
+ it_behaves_like "by quarter"
27
+ it_behaves_like "by week"
28
+ it_behaves_like "by weekend"
29
+ it_behaves_like "by year"
30
+
31
+ it "should be able to order the result set" do
32
+ scope = Post.by_year(Time.zone.now.year, :order => "created_at DESC")
33
+ scope.order_values.should == ["created_at DESC"]
34
+ end
35
+
36
+ describe "#between" do
37
+ it "should return an ActiveRecord::Relation object" do
38
+ Post.between(Date.today - 2, Date.today).class.should == ActiveRecord::Relation
39
+ end
40
+ it "should return a result set between two times" do
41
+ Post.between(Date.today - 2, Date.today).count.should == 1
42
+ end
43
+ end
44
+
45
+ describe "#between_times" do
46
+ it "should be an alias of #between" do
47
+ Post.between_times(Date.today - 2, Date.today).should == Post.between(Date.today - 2, Date.today)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ Dir[File.dirname(__FILE__) + '/../shared/*.rb'].each {|file| require file }
3
+
4
+ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3') do
5
+
6
+ before(:all) do
7
+ DATABASE_NAME = "mongoid_#{Process.pid}"
8
+
9
+ Mongoid.configure do |config|
10
+ config.connect_to DATABASE_NAME
11
+ end
12
+
13
+ load File.dirname(__FILE__) + "/../../fixtures/mongoid/models.rb"
14
+ load File.dirname(__FILE__) + "/../../fixtures/shared/seeds.rb"
15
+ end
16
+
17
+ after(:all) do
18
+ Mongoid.purge!
19
+ end
20
+
21
+ it_behaves_like "by day"
22
+ it_behaves_like "by direction"
23
+ it_behaves_like "by fortnight"
24
+ it_behaves_like "by month"
25
+ it_behaves_like "by quarter"
26
+ it_behaves_like "by week"
27
+ it_behaves_like "by weekend"
28
+ it_behaves_like "by year"
29
+
30
+ describe "#between" do
31
+ it "should return a Mongoid::Critera object" do
32
+ Post.between(Date.today - 2, Date.today).class.should == Mongoid::Criteria
33
+ end
34
+ it "should return a result set between two times" do
35
+ Post.between(Date.today - 2, Date.today).count.should == 1
36
+ end
37
+ end
38
+
39
+ describe "#between_times" do
40
+ it "should be an alias of #between" do
41
+ Post.between_times(Date.today - 2, Date.today).should == Post.between(Date.today - 2, Date.today)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "by day" do
4
+ describe "by day" do
5
+ def posts_count(*args)
6
+ Post.by_day(*args).count
7
+ end
8
+
9
+ it "should be able to find a post for today" do
10
+ posts_count.should eql(4)
11
+ end
12
+
13
+ it "should be able to find a post by a given date in last year" do
14
+ posts_count(:year => Time.zone.now.year - 1).should eql(1)
15
+ end
16
+
17
+ it "should be able to use an alternative field" do
18
+ Event.by_day(Time.now.yesterday, :field => "start_time").size.should eql(1)
19
+ end
20
+
21
+ it "should be able to use a date" do
22
+ posts_count(Date.today).should eql(4)
23
+ end
24
+
25
+ it "should be able to use a String" do
26
+ posts_count(Date.today.to_s).should eql(4)
27
+ end
28
+ end
29
+
30
+ describe "today" do
31
+ it "should show the post for today" do
32
+ Post.today.map(&:text).should include("Today's post")
33
+ end
34
+
35
+ it "should be able to use an alternative field" do
36
+ # Test may occur on an event day.
37
+ Event.today(:field => "start_time").size.should eql(1)
38
+ end
39
+ end
40
+
41
+ describe "yesterday" do
42
+
43
+ it "should show the post for yesterday" do
44
+ Post.yesterday.map(&:text).should include("Yesterday's post")
45
+ end
46
+
47
+ it "should be able to use an alternative field" do
48
+ Event.yesterday(:field => "start_time").size.should eql(1)
49
+ end
50
+
51
+ end
52
+
53
+ describe "tomorrow" do
54
+ it "should show the post for tomorrow" do
55
+ Post.tomorrow.map(&:text).should include("Tomorrow's post")
56
+ end
57
+
58
+ it "should be able to use an alternative field" do
59
+ Event.tomorrow(:field => "start_time").size.should eql(1)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "by direction" do
4
+ describe "before" do
5
+ def posts_count(*args)
6
+ Post.before(*args).count
7
+ end
8
+
9
+ it "should show the correct number of posts in the past" do
10
+ posts_count.should == 5
11
+ end
12
+
13
+ it "is aliased as before_now" do
14
+ Post.before_now.count.should == 5
15
+ end
16
+
17
+ it "should find for a given time" do
18
+ posts_count(Time.zone.now - 2.days).should eql(2)
19
+ end
20
+
21
+ it "should find for a given date" do
22
+ posts_count(Date.today - 2).should eql(2)
23
+ end
24
+
25
+ it "should find for a given string" do
26
+ posts_count("next tuesday").should eql(8)
27
+ end
28
+
29
+ it "raises an exception when Chronic can't parse" do
30
+ lambda { posts_count(";aosdjbjisdabdgofbi") }.should raise_error(ByStar::ParseError)
31
+ end
32
+
33
+ it "should be able to find all events before Ryan's birthday using a non-standard field" do
34
+ Event.before(Time.local(Time.zone.now.year+2), :field => "start_time").count.should eql(8)
35
+ end
36
+ end
37
+
38
+ describe "future" do
39
+ def posts_count(*args)
40
+ Post.after(*args).count
41
+ end
42
+
43
+ it "should show the correct number of posts in the future" do
44
+ Post.after.count.should eql(posts_count)
45
+ Post.after_now.count.should eql(posts_count)
46
+ end
47
+
48
+ it "should find for a given date" do
49
+ posts_count(Date.today - 2).should eql(19)
50
+ end
51
+
52
+ it "should find for a given string" do
53
+ posts_count("next tuesday").should eql(13)
54
+ end
55
+
56
+ it "should be able to find all events before Dad's birthday using a non-standard field" do
57
+ Event.after(Time.zone.local(Time.zone.now.year, 7, 5), :field => "start_time").count.should eql(3)
58
+ end
59
+ end
60
+
61
+ describe "previous and next" do
62
+ let(:current_post) { Post.find_by_text("post 1") }
63
+ let(:current_event) { Event.find_by_name("Mum's birthday!") }
64
+
65
+ context "previous" do
66
+ it "can find the previous post" do
67
+ current_post.previous.text.should == "Yesterday's post"
68
+ end
69
+
70
+ it "takes the field option" do
71
+ current_event.previous(:field => "start_time").name.should == "Dad's birthday!"
72
+ end
73
+ end
74
+
75
+ context "next" do
76
+ it "can find the next post" do
77
+ current_post.next.text.should == "Today's post"
78
+ end
79
+
80
+ it "takes the field option" do
81
+ current_event.next(:field => "start_time").name.should == "Ryan's birthday!"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "by fortnight" do
4
+ describe "by fortnight" do
5
+ def find_posts(*args)
6
+ Post.by_fortnight(*args)
7
+ end
8
+
9
+ def posts_count(*args)
10
+ find_posts(*args).count
11
+ end
12
+
13
+ it "should be able to find posts in the current fortnight" do
14
+ posts_count.should eql(6)
15
+ end
16
+
17
+ it "should be able to find posts in the 1st fortnight of the current year" do
18
+ posts_count(0).should eql(6)
19
+ posts_count("0").should eql(6)
20
+ # There was previously a situation where incorrect time zone math
21
+ # caused the 'post 1' post to NOT appear, so count would be 7, rather than 8.
22
+ # So this line simply regression tests that problem.
23
+ Post.by_fortnight(0).map(&:text).should include("post 1")
24
+ end
25
+
26
+ it "should be able to find posts for a fortnight ago" do
27
+ posts_count(2.weeks.ago).should eql(2)
28
+ end
29
+
30
+ it "should be able to find posts for a given fortnight in a year" do
31
+ posts_count(0, :year => Time.zone.now.year - 1).should eql(1)
32
+ end
33
+
34
+ it "should be able to find posts for the current fortnight in a specific year" do
35
+ posts_count(:year => Time.zone.now.year - 1).should eql(1)
36
+ end
37
+
38
+ it "should raise an error when given an invalid argument" do
39
+ 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).")
40
+ end
41
+
42
+ it "should be able to use an alternative field" do
43
+ Event.by_fortnight(nil, :field => "start_time").count.should eql(2)
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "by month" do
4
+ describe "by month" do
5
+ def find_posts(time=Time.zone.now, options={})
6
+ Post.by_month(time, options)
7
+ end
8
+
9
+ def posts_count(time=Time.zone.now, options={})
10
+ find_posts(time, options).count
11
+ end
12
+
13
+ it "should be able to find posts for the current month" do
14
+ posts_count.should eql(6)
15
+ end
16
+
17
+ it "should be able to find a single post for January" do
18
+ # If it is January we'll have all the "current" posts in there.
19
+ # This makes the count 10.
20
+ # I'm sure you can guess what happens when it's not January.
21
+ posts_count("January").should eql(6)
22
+ end
23
+
24
+ it "should be able to find two posts for the 2nd month" do
25
+ # If it is February we'll have all the "current" posts in there.
26
+ # This makes the count 10.
27
+ # I'm sure you can guess what happens when it's not February.
28
+ posts_count(2).should eql(1)
29
+ end
30
+
31
+ it "should be able to find three posts for the 3rd month, using time instance" do
32
+ # If it is March we'll have all the "current" posts in there.
33
+ # This makes the count 10.
34
+ # I'm sure you can guess what happens when it's not March.
35
+ time = Time.local(Time.zone.now.year, 3, 1)
36
+ posts_count(time).should eql(1)
37
+ end
38
+
39
+ it "should be able to find a single post from January last year" do
40
+ posts_count("January", :year => Time.zone.now.year - 1).should eql(1)
41
+ end
42
+
43
+ it "should fail when given incorrect months" do
44
+ lambda { find_posts(0) }.should raise_error(ByStar::ParseError)
45
+ lambda { find_posts(13) }.should raise_error(ByStar::ParseError)
46
+ lambda { find_posts("Ryan") }.should raise_error(ByStar::ParseError)
47
+ # LOL arrays
48
+ lambda { find_posts([1,2,3]) }.should raise_error(NoMethodError)
49
+ end
50
+
51
+ it "should be able to use an alternative field" do
52
+ Timecop.freeze(Time.zone.local(Time.zone.now.year, 12, 1, 0, 0, 0)) do
53
+ Event.by_month(:field => "start_time").size.should eql(1)
54
+ end
55
+ end
56
+
57
+ it "should be able to specify the year as a string" do
58
+ posts_count(1, :year => (Time.zone.now.year - 1).to_s).should eql(1)
59
+ end
60
+
61
+ it "should be able to accept time datatype" do
62
+ posts_count(Time.now - 1.year).should eql(1)
63
+ end
64
+
65
+ it "should be able to accept date datatype" do
66
+ posts_count(Date.today - 1.year).should eql(1)
67
+ end
68
+ end
69
+
70
+ describe "by calendar month" do
71
+ def find_posts(time=Time.zone.now, options={})
72
+ Post.by_calendar_month(time, options)
73
+ end
74
+
75
+ def posts_count(time=Time.zone.now, options={})
76
+ find_posts(time, options).count
77
+ end
78
+
79
+ it "should be able to find posts for the current calendar month" do
80
+ posts_count.should eql(8)
81
+ end
82
+
83
+ it "should be able to find a single post for January calendar month" do
84
+ # If it is January we'll have all the "current" posts in there.
85
+ # This makes the count 10.
86
+ # I'm sure you can guess what happens when it's not January.
87
+ posts_count("January").should eql(8)
88
+ end
89
+
90
+ it "should be able to find two posts for the 2nd calendar month" do
91
+ # If it is February we'll have all the "current" posts in there.
92
+ # This makes the count 10.
93
+ # I'm sure you can guess what happens when it's not February.
94
+ posts_count(2).should eql(2)
95
+ end
96
+
97
+ it "should be able to find three posts for the 3rd calendar month, using time instance" do
98
+ # If it is March we'll have all the "current" posts in there.
99
+ # This makes the count 10.
100
+ # I'm sure you can guess what happens when it's not March.
101
+ time = Time.local(Time.zone.now.year, 3, 1)
102
+ posts_count(time).should eql(1)
103
+ end
104
+
105
+ it "should be able to find a single post from January last year" do
106
+ posts_count("January", :year => Time.zone.now.year - 1).should eql(1)
107
+ end
108
+ end
109
+ end