temporal_scopes 0.0.1 → 0.0.2
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/README.md +3 -1
- data/lib/temporal_scopes/has_temporal_scopes.rb +102 -15
- data/lib/temporal_scopes/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0bb59fb20ec57703464efa1db45f23340de3450
|
4
|
+
data.tar.gz: baeec6001c3138410bd94561be1339292948b4fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3936bb8540a87a2f6aff81483a0e6ee5e3fa623466bb5c7c426097342280e74add1ff5b92b66c14c95f99b114d077ebade22b186b106ff7d27560c7c7cdc4c51
|
7
|
+
data.tar.gz: ff2003aff6d0c39d4a0fef33490dc95e73da1d2a062596b60ba6fb74e9d3c8f9c597626f2c10c457b2bf9efaee8711848c35ebb5454433b5542e8c1a312796d3
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# TemporalScopes [](https://travis-ci.org/fiedl/temporal_scopes)
|
1
|
+
# TemporalScopes [](https://travis-ci.org/fiedl/temporal_scopes) [](http://badge.fury.io/rb/temporal_scopes)
|
2
2
|
|
3
3
|
Providing temporal scopes for an ActiveRecord model to allow queries by time. For example, `MyModel.now.where(...)`, `my_model.archive`, `MyModel.past.where(...)`.
|
4
4
|
|
@@ -50,7 +50,9 @@ Further [documentation can be found on rubydoc.info](http://rubydoc.info/github/
|
|
50
50
|
|
51
51
|
### Caveats
|
52
52
|
|
53
|
+
* This gem requires Rails 4.
|
53
54
|
* There is only one `valid_from` and one `valid_to` time per object. Therefore, you can't keep track of first archiving an object and later un-archiving it. Un-archiving an object loses the information of first archiving it.
|
55
|
+
* Currently, the future is not handled (`Article.future` and `article.archive at: 1.hour.from.now` do not work.) But this is planned to be implemented in the future.
|
54
56
|
|
55
57
|
## Installation
|
56
58
|
|
@@ -3,38 +3,125 @@ require 'active_record'
|
|
3
3
|
module TemporalScopes
|
4
4
|
module HasTemporalScopes
|
5
5
|
|
6
|
+
# Adds scopes and methods for handing temporal filtering.
|
7
|
+
#
|
8
|
+
# ## Make an `ActiveRecord` have temporal scopes
|
9
|
+
#
|
10
|
+
# class Article < ActiveRecord::Base
|
11
|
+
# has_temporal_scopes
|
12
|
+
#
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# ## Archive an object
|
16
|
+
#
|
17
|
+
# current_article = Article.create(title: 'My new article', body: 'Lorem ipsum')
|
18
|
+
#
|
19
|
+
# past_article = Article.create(title: 'My new article', body: 'Lorem ipsum')
|
20
|
+
# past_article.archive
|
21
|
+
#
|
22
|
+
# # or provide a datetime:
|
23
|
+
# past_article.archive at: 1.hour.ago
|
24
|
+
#
|
25
|
+
# ## Use temporal scopes for filtering
|
26
|
+
#
|
27
|
+
# Article.now # => [current_article]
|
28
|
+
# Article.past # => [past_article]
|
29
|
+
# Article.with_past # => [current_article, past_article]
|
30
|
+
#
|
31
|
+
# Note that the **default scope** is set to `now`.
|
32
|
+
#
|
33
|
+
# Article.all # => [current_article]
|
34
|
+
# Article.now # => [current_article]
|
35
|
+
# Article.with_past # => [current_article, past_article]
|
36
|
+
# Article.without_temporal_condition # => [current_article, past_article]
|
37
|
+
#
|
6
38
|
def has_temporal_scopes
|
7
39
|
|
8
|
-
scope :without_temporal_condition, -> {
|
9
|
-
relation = unscope(where: [:valid_from, :valid_to])
|
10
|
-
relation.where_values.delete_if { |query| query.to_sql.include?("\"valid_from\"") || query.to_sql.include?("\"valid_to\"") }
|
11
|
-
relation
|
12
|
-
}
|
13
|
-
|
14
|
-
scope :now, -> {
|
15
|
-
without_temporal_condition
|
16
|
-
.where(arel_table[:valid_from].eq(nil).or(arel_table[:valid_from].lteq(Time.zone.now)))
|
17
|
-
.where(arel_table[:valid_to].eq(nil).or(arel_table[:valid_to].gteq(Time.zone.now)))
|
18
|
-
}
|
19
|
-
scope :past, -> { without_temporal_condition.where('valid_to < ?', Time.zone.now) }
|
20
|
-
scope :with_past, -> { without_temporal_condition }
|
21
|
-
|
22
40
|
default_scope { now }
|
23
41
|
|
24
42
|
extend ClassMethods
|
25
43
|
include InstanceMethods
|
26
44
|
end
|
27
45
|
|
46
|
+
# The following class methods and scopes are added to
|
47
|
+
# `ActiveRecord::Base` classes that have been called
|
48
|
+
# `has_temporal_scopes` on.
|
49
|
+
#
|
28
50
|
module ClassMethods
|
51
|
+
|
52
|
+
# Removes temporal conditions from the query.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# Article.where(valid_to: 10.days.ago..1.day.ago) # => [] (due to default scope.)
|
56
|
+
# Article.without_temporal_condition.where(valid_to: 10.days.ago..1.day.ago) # returns the desired articles.
|
57
|
+
#
|
58
|
+
# @return [ActiveRecord::Relation] the relation without temporal conditions on `valid_from` and `valid_to`.
|
59
|
+
#
|
60
|
+
def without_temporal_condition
|
61
|
+
relation = unscope(where: [:valid_from, :valid_to])
|
62
|
+
relation.where_values.delete_if { |query| query.to_sql.include?("\"valid_from\"") || query.to_sql.include?("\"valid_to\"") } if relation && relation.where_values
|
63
|
+
relation
|
64
|
+
end
|
65
|
+
|
66
|
+
# Filters for only current objects.
|
67
|
+
#
|
68
|
+
# This is the default scope.
|
69
|
+
#
|
70
|
+
# @return [ActiveRecord::Relation] only current objects.
|
71
|
+
#
|
72
|
+
def now
|
73
|
+
without_temporal_condition
|
74
|
+
.where(arel_table[:valid_from].eq(nil).or(arel_table[:valid_from].lteq(Time.zone.now)))
|
75
|
+
.where(arel_table[:valid_to].eq(nil).or(arel_table[:valid_to].gteq(Time.zone.now)))
|
76
|
+
end
|
77
|
+
|
78
|
+
# Filters for only past objects.
|
79
|
+
#
|
80
|
+
# @return [ActiveRecord::Relation] only past objects.
|
81
|
+
#
|
82
|
+
# @example Getting only archived articles by an author.
|
83
|
+
# author.articles.past
|
84
|
+
#
|
85
|
+
def past
|
86
|
+
without_temporal_condition.where('valid_to < ?', Time.zone.now)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Removes the filters such that past and present
|
90
|
+
# objects are returned.
|
91
|
+
#
|
92
|
+
# @return [ActiveRecord::Relation] past and current objects.
|
93
|
+
#
|
94
|
+
def with_past
|
95
|
+
without_temporal_condition
|
96
|
+
end
|
97
|
+
|
29
98
|
end
|
30
|
-
|
99
|
+
|
100
|
+
# The following instance methods are added to
|
101
|
+
# `ActiveRecord::Base` objects, which classes have
|
102
|
+
# been called `has_temporal_scopes` on.
|
103
|
+
#
|
31
104
|
module InstanceMethods
|
32
105
|
|
106
|
+
# Archives an object, that is, makes it a past object.
|
107
|
+
#
|
108
|
+
# @param params [Hash] a hash of parameters.
|
109
|
+
# @option params :at [DateTime] (Time.zonw.now) when to archive the object, i.e. the time when the present object becomes a past object, i.e. expires.
|
110
|
+
#
|
111
|
+
# @return [ActiveRecord::Base] the archived object.
|
112
|
+
#
|
113
|
+
# @example Archiving an object now.
|
114
|
+
# article.archive
|
115
|
+
#
|
116
|
+
# @example Archiving an object with effect 4 hours ago.
|
117
|
+
# article.archive at: 4.hours.ago
|
118
|
+
#
|
33
119
|
def archive(params = {})
|
34
120
|
unless self.valid_to
|
35
121
|
archive_at = params[:at] || Time.zone.now
|
36
122
|
update_attribute(:valid_to, archive_at)
|
37
123
|
end
|
124
|
+
return self
|
38
125
|
end
|
39
126
|
|
40
127
|
end
|