by_star 2.0.0.beta1 → 2.1.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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