season 0.2 → 0.3
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +19 -6
- data/lib/season.rb +20 -6
- data/lib/season/instance_method_builder.rb +45 -0
- data/lib/season/legacy.rb +2 -1
- data/lib/season/scope_builder.rb +17 -15
- data/lib/season/version.rb +1 -1
- data/season.gemspec +2 -1
- data/spec/scopes_spec.rb +85 -17
- data/spec/spec_helper.rb +14 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee585a77f75b912e9967cee60051590a4df64ddb
|
4
|
+
data.tar.gz: db1c30b2d54d0bec8f2e36c0b10cfa6b657150b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f2d10ab32b50dbf017b57ba7ffbf31bcd38186aadd43ec23faa49f32b90279531c648caa9fc21d6e0cc0ac057d1f0faa5c936507f8e24427e3be9d6ca876a8e
|
7
|
+
data.tar.gz: 874d00169c9fc23a75f37c57ec75e08aca1b3ffd9881dd6950b9891e65d1f7597246162fca0f948fe16913d998810adbb82c184ed1c8d07d2251a7e0b449a469
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -26,7 +26,7 @@ In this first version Season only supports ActiveRecord, but we plan to also sup
|
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
|
-
To use Season scopes just append `_before`, `_after` or `_between` to your datetime column names and pass the arguments accordingly. See this:
|
29
|
+
To use Season scopes just append `_before`, `_after` or `_between` to your date/datetime/timestamp column names and pass the arguments accordingly. See this:
|
30
30
|
|
31
31
|
First, include Season in your model(s):
|
32
32
|
```ruby
|
@@ -36,6 +36,8 @@ class User < ActiveRecord::Base
|
|
36
36
|
end
|
37
37
|
```
|
38
38
|
|
39
|
+
### Scopes
|
40
|
+
|
39
41
|
Now, considering that our `User` class has three datetime columns named `:created_at`, `:updated_at` and `:confirmed_at`, the following scopes will be automatically available:
|
40
42
|
```ruby
|
41
43
|
# * Time/DateTime/String instances are allowed as arguments.
|
@@ -43,14 +45,17 @@ Now, considering that our `User` class has three datetime columns named `:create
|
|
43
45
|
User.created_at_before(Time.now)
|
44
46
|
User.created_at_after(DateTime.now)
|
45
47
|
User.created_at_between(Time.now - 1.week, '31-01-2015')
|
48
|
+
# => [ActiveRecord::Relation of Users]
|
46
49
|
|
47
50
|
User.updated_at_before(DateTime.now)
|
48
51
|
User.updated_at_after('01-01-2015')
|
49
52
|
User.updated_at_between(Time.now - 1.week, Time.now)
|
53
|
+
# => [ActiveRecord::Relation of Users]
|
50
54
|
|
51
55
|
User.confirmed_at_before('01-01-2015')
|
52
56
|
User.confirmed_at_after(DateTime.now)
|
53
57
|
User.confirmed_at_between(Time.now - 1.year, Time.now - 1.week)
|
58
|
+
# => [ActiveRecord::Relation of Users]
|
54
59
|
```
|
55
60
|
|
56
61
|
They are chainable, so you can also do things like this:
|
@@ -59,13 +64,21 @@ User.where(id: [1, 2, 3]).created_before(Time.now)
|
|
59
64
|
User.updated_after('01-01-2015').order(created_at: :asc)
|
60
65
|
```
|
61
66
|
|
67
|
+
### Instance methods
|
68
|
+
|
69
|
+
Other than scopes, useful instance methos will also be available:
|
70
|
+
```ruby
|
71
|
+
joe = User.first
|
72
|
+
|
73
|
+
joe.created_at_before?(Time.now)
|
74
|
+
joe.updated_at_after?('10-10-2000')
|
75
|
+
joe.confirmed_at_between?('20-10-2013', DateTime.now)
|
76
|
+
# => true or false
|
77
|
+
```
|
78
|
+
|
62
79
|
## To Do
|
63
80
|
|
64
|
-
-
|
65
|
-
- Support other ORMs (Mongoid, 'insert-more-here')
|
66
|
-
- Add Error Handling
|
67
|
-
- Add helpers for instances (like `User.first.created_before?('01-02-2015')`)
|
68
|
-
- Add support for queries with joins
|
81
|
+
- Support other ORMs (Mongoid, ...?)
|
69
82
|
|
70
83
|
## Contributing
|
71
84
|
|
data/lib/season.rb
CHANGED
@@ -3,6 +3,7 @@ require "season/configuration"
|
|
3
3
|
require "season/legacy"
|
4
4
|
require "season/scope_builder"
|
5
5
|
require "season/query_builder"
|
6
|
+
require "season/instance_method_builder"
|
6
7
|
|
7
8
|
module Season
|
8
9
|
|
@@ -11,22 +12,35 @@ module Season
|
|
11
12
|
def self.included(base)
|
12
13
|
base.extend(ClassMethods)
|
13
14
|
|
14
|
-
|
15
|
+
# Define scopes
|
16
|
+
sb = ScopeBuilder.new(base)
|
17
|
+
base.class_eval do
|
18
|
+
base.date_or_time_column_names.each do |column_name|
|
19
|
+
QUERY_VERBS.each do |query_verb|
|
20
|
+
sb.build(table_name, column_name, query_verb)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
15
24
|
|
25
|
+
# Define instance methods
|
26
|
+
imb = InstanceMethodBuilder.new(base)
|
16
27
|
base.class_eval do
|
17
|
-
|
18
|
-
base.datetime_column_names.each do |column_name|
|
28
|
+
base.date_or_time_column_names.each do |column_name|
|
19
29
|
QUERY_VERBS.each do |query_verb|
|
20
|
-
|
30
|
+
imb.build(table_name, column_name, query_verb)
|
21
31
|
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
26
36
|
module ClassMethods
|
27
|
-
def
|
28
|
-
columns.map { |c| c.name if c.type == :datetime }.compact
|
37
|
+
def date_or_time_column_names
|
38
|
+
columns.map { |c| c.name if c.type == :datetime || c.type == :date }.compact
|
29
39
|
end
|
30
40
|
end
|
41
|
+
|
42
|
+
def self.root
|
43
|
+
File.expand_path '../..', __FILE__
|
44
|
+
end
|
31
45
|
end
|
32
46
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Season
|
2
|
+
class InstanceMethodBuilder
|
3
|
+
|
4
|
+
def initialize(klass)
|
5
|
+
@klass = klass
|
6
|
+
end
|
7
|
+
|
8
|
+
def build(table_name, column_name, query_verb)
|
9
|
+
method_val = self.send(query_verb, column_name)
|
10
|
+
|
11
|
+
@klass.class_eval %Q{
|
12
|
+
def #{column_name}_#{query_verb}?(*args)
|
13
|
+
#{method_val}
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_input(date_input)
|
21
|
+
date_input= case date_input.class
|
22
|
+
when Time || Date || ActiveSupport::TimeWithZone
|
23
|
+
date_input.to_i
|
24
|
+
when DateTime
|
25
|
+
date_input
|
26
|
+
when String
|
27
|
+
DateTime.parse(date_input)
|
28
|
+
else
|
29
|
+
raise ArgumentError, 'Invalid date_to_compare to compare.'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def before(column_name)
|
34
|
+
"#{column_name} < args.first"
|
35
|
+
end
|
36
|
+
|
37
|
+
def after(column_name)
|
38
|
+
"#{column_name} > args.first"
|
39
|
+
end
|
40
|
+
|
41
|
+
def between(column_name)
|
42
|
+
"#{column_name} > args.first || #{column_name} < args.last"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/season/legacy.rb
CHANGED
data/lib/season/scope_builder.rb
CHANGED
@@ -9,26 +9,28 @@ module Season
|
|
9
9
|
def build(table_name, column_name, query_verb)
|
10
10
|
unless method_exists?(column_name)
|
11
11
|
query_str = @query_builder.build(table_name, column_name, query_verb)
|
12
|
-
|
13
|
-
@klass.
|
14
|
-
|
15
|
-
|
12
|
+
|
13
|
+
@klass.instance_eval %Q{
|
14
|
+
def #{column_name}_#{query_verb}(*args)
|
15
|
+
#{query_str}
|
16
|
+
end
|
17
|
+
}
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
def method_exists?(column_name)
|
24
|
+
defined? @klass.column_name
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
def adapter_class_name
|
28
|
+
return 'active_record' if @klass < ActiveRecord::Base
|
29
|
+
raise "Database adapter not supported."
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
32
|
+
# def remove_old_suffix(text)
|
33
|
+
# text.sub(/(#{POPULAR_SUFFIXES.join('|')})$/, '') || text
|
34
|
+
# end
|
35
|
+
end
|
34
36
|
end
|
data/lib/season/version.rb
CHANGED
data/season.gemspec
CHANGED
@@ -26,5 +26,6 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "activerecord", "~> 4.0"
|
27
27
|
spec.add_development_dependency "rubocop", "~> 0.29"
|
28
28
|
spec.add_development_dependency "rubocop-rspec", "~> 1.2"
|
29
|
-
spec.add_development_dependency "sqlite3", "~> 1.3"
|
29
|
+
spec.add_development_dependency "sqlite3", "~> 1.3"
|
30
|
+
spec.add_development_dependency "database_cleaner", "~> 1.4"
|
30
31
|
end
|
data/spec/scopes_spec.rb
CHANGED
@@ -12,6 +12,7 @@ ActiveRecord::Base.connection.instance_eval do
|
|
12
12
|
create_table :users do |t|
|
13
13
|
t.datetime :created_at
|
14
14
|
t.datetime :updated_at
|
15
|
+
t.date :birthdate
|
15
16
|
t.timestamp :confirmed_at
|
16
17
|
end
|
17
18
|
end
|
@@ -27,28 +28,95 @@ end
|
|
27
28
|
RSpec.describe Season do
|
28
29
|
subject { User }
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
.
|
33
|
-
|
31
|
+
describe 'defined datetime scopes' do
|
32
|
+
it 'of datetime type' do
|
33
|
+
expect(subject).to respond_to(:created_at_before, :created_at_after)
|
34
|
+
.with(1).argument
|
35
|
+
expect(subject).to respond_to(:created_at_between).with(2).arguments
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'of date type' do
|
39
|
+
expect(subject).to respond_to(:birthdate_before, :birthdate_after)
|
40
|
+
.with(1).argument
|
41
|
+
expect(subject).to respond_to(:birthdate_between).with(2).arguments
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'of timestamp type' do
|
45
|
+
expect(subject).to respond_to(:confirmed_at_before, :confirmed_at_after)
|
46
|
+
.with(1).argument
|
47
|
+
expect(subject).to respond_to(:confirmed_at_between).with(2).arguments
|
48
|
+
end
|
49
|
+
|
50
|
+
it ' - legacy' do
|
51
|
+
expect(subject).to respond_to(:created_before, :created_after)
|
52
|
+
.with(1).argument
|
53
|
+
expect(subject).to respond_to(:created_between).with(2).arguments
|
54
|
+
expect(subject).to respond_to(:updated_before, :updated_after)
|
55
|
+
.with(1).argument
|
56
|
+
expect(subject).to respond_to(:updated_between).with(2).arguments
|
57
|
+
end
|
34
58
|
end
|
35
59
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
60
|
+
describe 'datetime scopes' do
|
61
|
+
|
62
|
+
let(:instant) { DateTime.parse('01-01-2015') }
|
63
|
+
|
64
|
+
before do
|
65
|
+
User.create!(created_at: instant - 1.year)
|
66
|
+
User.create!(created_at: instant + 1.year)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "shows correct results for 'before'" do
|
70
|
+
expect(subject.created_at_before(instant).count).to eq(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "shows correct results for 'after'" do
|
74
|
+
expect(subject.created_at_after(instant).count).to eq(1)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "shows correct results for 'between'" do
|
78
|
+
expect(subject.created_at_between(instant - 2.year, instant + 2.year).count).to eq(2)
|
79
|
+
end
|
40
80
|
end
|
41
81
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
.
|
48
|
-
|
82
|
+
describe 'defined datetime instance methods' do
|
83
|
+
|
84
|
+
let(:user) { User.new }
|
85
|
+
|
86
|
+
it 'of datetime type' do
|
87
|
+
expect(user).to respond_to(:created_at_before?, :created_at_after?)
|
88
|
+
.with(1).argument
|
89
|
+
expect(user).to respond_to(:created_at_between?).with(2).arguments
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'of date type' do
|
93
|
+
expect(user).to respond_to(:birthdate_before?, :birthdate_after?)
|
94
|
+
.with(1).argument
|
95
|
+
expect(user).to respond_to(:birthdate_between?).with(2).arguments
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'of timestamp type' do
|
99
|
+
expect(user).to respond_to(:confirmed_at_before?, :confirmed_at_after?)
|
100
|
+
.with(1).argument
|
101
|
+
expect(user).to respond_to(:confirmed_at_between?).with(2).arguments
|
102
|
+
end
|
49
103
|
end
|
50
104
|
|
51
|
-
|
52
|
-
|
105
|
+
describe 'datetime instance methods' do
|
106
|
+
|
107
|
+
let(:instant) { DateTime.parse('01-01-2015') }
|
108
|
+
let(:user) { User.create!(created_at: instant) }
|
109
|
+
|
110
|
+
it "shows correct results for 'before'" do
|
111
|
+
expect(user.created_at_before?(instant + 1.day)).to eq(true)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "shows correct results for 'after'" do
|
115
|
+
expect(user.created_at_after?(instant - 1.day)).to eq(true)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "shows correct results for 'between'" do
|
119
|
+
expect(user.created_at_between?(instant - 1.day, instant + 1.day)).to eq(true)
|
120
|
+
end
|
53
121
|
end
|
54
122
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'season'
|
2
|
+
require 'database_cleaner'
|
2
3
|
require "codeclimate-test-reporter"
|
3
4
|
CodeClimate::TestReporter.start
|
4
5
|
|
@@ -10,4 +11,17 @@ RSpec.configure do |config|
|
|
10
11
|
config.mock_with :rspec do |mocks|
|
11
12
|
mocks.verify_partial_doubles = true
|
12
13
|
end
|
14
|
+
|
15
|
+
config.before(:suite) do
|
16
|
+
DatabaseCleaner.strategy = :truncation
|
17
|
+
DatabaseCleaner.clean_with :truncation
|
18
|
+
end
|
19
|
+
|
20
|
+
config.before(:each) do
|
21
|
+
DatabaseCleaner.start
|
22
|
+
end
|
23
|
+
|
24
|
+
config.after(:each) do
|
25
|
+
DatabaseCleaner.clean
|
26
|
+
end
|
13
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: season
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joao Diogo Costa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: database_cleaner
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.4'
|
111
125
|
description: Season automatically creates scopes for your models' datetime columns.
|
112
126
|
email:
|
113
127
|
- jdscosta91@gmail.com
|
@@ -125,6 +139,7 @@ files:
|
|
125
139
|
- Rakefile
|
126
140
|
- lib/season.rb
|
127
141
|
- lib/season/configuration.rb
|
142
|
+
- lib/season/instance_method_builder.rb
|
128
143
|
- lib/season/legacy.rb
|
129
144
|
- lib/season/query_builder.rb
|
130
145
|
- lib/season/scope_builder.rb
|