mongoid-metastamp 0.0.2 → 0.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.
- data/README.md +60 -33
- data/lib/mongoid/metastamp.rb +0 -2
- data/lib/mongoid/metastamp/time.rb +8 -2
- data/lib/mongoid/metastamp/version.rb +1 -1
- data/mongoid-metastamp.gemspec +1 -2
- data/spec/spec_helper.rb +0 -2
- data/spec/time_compatibility_spec.rb +1 -1
- data/spec/time_search_spec.rb +6 -6
- data/spec/time_storage_spec.rb +1 -1
- metadata +43 -60
- data/lib/mongoid/core_ext.rb +0 -26
data/README.md
CHANGED
@@ -10,22 +10,22 @@ What It Does
|
|
10
10
|
(Or why would I want to use this?)
|
11
11
|
|
12
12
|
Storing simple timestamps is all well and good if your queries are simple or involve just one timezone.
|
13
|
-
But sometimes you need to search
|
14
|
-
|
13
|
+
But sometimes you need to search for each timestamp relative to the timezone it was created in.
|
14
|
+
This is common when you have more than one location. For example:
|
15
15
|
|
16
|
-
* Find all flights that depart from
|
17
|
-
* Return all employees that clocked in
|
16
|
+
* Find all flights that depart from all airports between 1:00pm and 2:00pm local (airport) time.
|
17
|
+
* Return all employees that clocked in later than 8:00am local time to any of our nationwide locations.
|
18
18
|
|
19
19
|
Other times you want to be able to query very specific parts of the
|
20
|
-
date
|
20
|
+
date or time that typically can't be accessed without parsing it:
|
21
21
|
|
22
|
-
* Find all transactions that
|
23
|
-
* Return all users that signed up
|
22
|
+
* Find all transactions that occurred on weekdays after 12pm in 2010.
|
23
|
+
* Return all users that signed up the first week of every month over the last 3 years.
|
24
24
|
|
25
25
|
Typically to do these things, you'd need to add a bunch of of complex time ranges to your query.
|
26
26
|
Or you might query the entire range and loop through each result, running additional tests on the parsed time.
|
27
27
|
|
28
|
-
Using mongoid-metastamp gives you a custom time field type that is normalized beforehand,
|
28
|
+
Using mongoid-metastamp gives you a custom time field type that is normalized and parsed beforehand,
|
29
29
|
and then stored in a MongoDB friendly way for easy querying.
|
30
30
|
|
31
31
|
|
@@ -56,17 +56,24 @@ end
|
|
56
56
|
```
|
57
57
|
|
58
58
|
```ruby
|
59
|
-
|
60
|
-
|
61
|
-
event =
|
62
|
-
event.
|
63
|
-
|
59
|
+
event = MyEvent.new
|
60
|
+
event.starts_at = Time.now
|
61
|
+
event.ends_at = Time.now + 1.day
|
62
|
+
event.save
|
63
|
+
# => true
|
64
|
+
|
65
|
+
event.starts_at
|
66
|
+
# => Wed, 5 Oct 2011 20:46:22 UTC +00:00
|
67
|
+
event.ends_at
|
68
|
+
# => Thu, 6 Oct 2011 20:46:31 UTC +00:00
|
64
69
|
```
|
65
70
|
|
71
|
+
|
66
72
|
Data Stored
|
67
73
|
=========================
|
68
74
|
|
69
|
-
|
75
|
+
However, behind the scenes the following meta fields will transparently be stored inside
|
76
|
+
your Mongoid::Metastamp::Time field:
|
70
77
|
|
71
78
|
* `time` (Date)
|
72
79
|
* `normalized` (Date)
|
@@ -81,29 +88,49 @@ When you define a `Mongoid::Metastamp::Time` field, the following meta fields al
|
|
81
88
|
* `offset` (Int)
|
82
89
|
|
83
90
|
|
84
|
-
|
85
|
-
It will also be the value deserialized when you access the field.
|
91
|
+
So given a field named `timestamp`:
|
86
92
|
|
87
93
|
```ruby
|
88
|
-
|
94
|
+
class MyEvent
|
95
|
+
include Mongoid::Document
|
96
|
+
field :timestamp, type: Mongoid::Metastamp::Time
|
97
|
+
end
|
89
98
|
```
|
90
99
|
|
91
|
-
|
100
|
+
You can access the raw metadata fields like this:
|
92
101
|
|
93
102
|
```ruby
|
94
|
-
event = MyEvent.new(
|
103
|
+
event = MyEvent.new(timestamp: "2011-10-05 10:00:00 -0800")
|
104
|
+
|
105
|
+
event['timestamp']
|
106
|
+
# => {"time"=>2011-10-05 17:00:00 UTC, "normalized"=>2011-10-05 10:00:00 UTC, "year"=>2011, "month"=>10, "day"=>5, "wday"=>3, "hour"=>10, "min"=>0, "sec"=>0, "zone"=>"-08:00", "offset"=>-25200}
|
107
|
+
|
95
108
|
event['timestamp']['month'] # => 10
|
96
109
|
event['timestamp']['day'] # => 5
|
97
110
|
event['timestamp']['year'] # => 2011
|
98
|
-
event['timestamp']['zone'] # => "-
|
111
|
+
event['timestamp']['zone'] # => "-08:00"
|
112
|
+
```
|
113
|
+
|
114
|
+
The `time` meta-field is special and stores whatever you assign the field to.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
event['timestamp']['time']
|
118
|
+
# => 2011-10-05 17:00:00 UTC
|
119
|
+
```
|
120
|
+
|
121
|
+
It will also be the value deserialized when you access the `timestamp` field.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
event.timestamp
|
125
|
+
# => Wed, 05 Oct 2011 17:00:00 UTC +00:00
|
99
126
|
```
|
100
127
|
|
101
128
|
The `normalized` meta-field is the time normalized to a UTC value.
|
102
129
|
This is useful when you want to query ignoring local offsets.
|
103
130
|
|
104
131
|
```ruby
|
105
|
-
eastern_event = MyEvent.new(timestamp: "2011-10-05 10:00:00 -
|
106
|
-
pacific_event = MyEvent.new(timestamp: "2011-10-05 10:00:00 -
|
132
|
+
eastern_event = MyEvent.new(timestamp: "2011-10-05 10:00:00 -0500")
|
133
|
+
pacific_event = MyEvent.new(timestamp: "2011-10-05 10:00:00 -0800")
|
107
134
|
|
108
135
|
eastern_event['timestamp']['time'] # => 2011-10-05 14:00:00 UTC
|
109
136
|
eastern_event['timestamp']['normalized'] # => 2011-10-05 10:00:00 UTC
|
@@ -116,37 +143,37 @@ pacific_event['timestamp']['normalized'] # => 2011-10-05 10:00:00 UTC
|
|
116
143
|
Querying
|
117
144
|
=========================
|
118
145
|
|
119
|
-
Since the `time` meta-field is the default, it can be queried as
|
146
|
+
Since the `time` meta-field is the default, it can be queried as just `timestamp`:
|
120
147
|
|
121
148
|
```ruby
|
122
149
|
good_old_days = Day.where(:timestamp.lt => 20.years.ago)
|
123
150
|
```
|
124
151
|
|
125
|
-
or
|
152
|
+
or as `timestamp.time`:
|
126
153
|
|
127
154
|
```ruby
|
128
155
|
good_old_days = Day.where("timestamp.time" => { '$lt' => 20.years.ago })
|
129
156
|
```
|
130
157
|
|
131
|
-
|
158
|
+
For now, the other meta-fields need to be queried using the full syntax:
|
132
159
|
|
133
160
|
```ruby
|
134
161
|
hump_days = Day.where("timestamp.wday" => 5)
|
135
|
-
=> Only Wednesdays
|
162
|
+
# => Only Wednesdays
|
136
163
|
|
137
|
-
|
138
|
-
=> Only between 12pm and 3pm
|
164
|
+
afternoon_delights = Delight.where("timestamp.hour" => { '$gte' => 12, '$lt' => 15 })
|
165
|
+
# => Only between 12pm and 3pm
|
139
166
|
```
|
140
|
-
See [search specs](https://github.com/sporkd/mongoid-metastamp/blob/master/spec/time_search_spec.rb)
|
141
|
-
for more
|
167
|
+
See the [search specs](https://github.com/sporkd/mongoid-metastamp/blob/master/spec/time_search_spec.rb)
|
168
|
+
for more examples.
|
142
169
|
|
143
170
|
|
144
171
|
Todo
|
145
172
|
======
|
146
173
|
|
147
|
-
* Add custom
|
148
|
-
* Migration
|
149
|
-
* Additional types
|
174
|
+
* Add custom finder methods and scopes
|
175
|
+
* Migration task to convert existing time fields
|
176
|
+
* Additional field types
|
150
177
|
|
151
178
|
|
152
179
|
License
|
data/lib/mongoid/metastamp.rb
CHANGED
@@ -4,7 +4,7 @@ module Mongoid #:nodoc:
|
|
4
4
|
module Metastamp
|
5
5
|
class Time
|
6
6
|
include Mongoid::Fields::Serializable
|
7
|
-
include Mongoid::Fields::
|
7
|
+
include Mongoid::Fields::Internal::Timekeeping
|
8
8
|
|
9
9
|
def deserialize(object)
|
10
10
|
return nil if object.blank?
|
@@ -18,7 +18,7 @@ module Mongoid #:nodoc:
|
|
18
18
|
date_time = parse_datetime(object)
|
19
19
|
{
|
20
20
|
time: time,
|
21
|
-
normalized: date_time
|
21
|
+
normalized: normalized_time(date_time),
|
22
22
|
year: date_time.year,
|
23
23
|
month: date_time.month,
|
24
24
|
day: date_time.day,
|
@@ -48,6 +48,12 @@ module Mongoid #:nodoc:
|
|
48
48
|
value
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def normalized_time(date_time)
|
53
|
+
d = ::Date._parse(date_time.to_s, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction).map { |arg| arg || 0 }
|
54
|
+
d[6] *= 1000000
|
55
|
+
::Time.utc_time(*d)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
data/mongoid-metastamp.gemspec
CHANGED
@@ -19,8 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency("mongoid", "~> 2.
|
23
|
-
s.add_development_dependency("bson_ext", "~> 1.3")
|
22
|
+
s.add_dependency("mongoid", "~> 2.4")
|
24
23
|
s.add_development_dependency("rake", "~> 0.9")
|
25
24
|
s.add_development_dependency("rspec", "~> 2.6")
|
26
25
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/time_search_spec.rb
CHANGED
@@ -9,11 +9,11 @@ describe "Mongoid::Metastamp::Time" do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
let :ten_am_eastern do
|
12
|
-
"2011-10-05T10:00:00-
|
12
|
+
"2011-10-05T10:00:00-05:00"
|
13
13
|
end
|
14
14
|
|
15
15
|
let :ten_am_pacific do
|
16
|
-
"2011-10-05T10:00:00-
|
16
|
+
"2011-10-05T10:00:00-08:00"
|
17
17
|
end
|
18
18
|
|
19
19
|
context "given a 10:00 eastern and a 10:00 pacific timestamp" do
|
@@ -196,12 +196,12 @@ describe "Mongoid::Metastamp::Time" do
|
|
196
196
|
|
197
197
|
describe "searching by timestamp.zone" do
|
198
198
|
|
199
|
-
it "should return only the eastern event when searching -
|
200
|
-
Event.where("timestamp.zone" => "-
|
199
|
+
it "should return only the eastern event when searching -05:00" do
|
200
|
+
Event.where("timestamp.zone" => "-05:00").to_a.should == [@eastern_event]
|
201
201
|
end
|
202
202
|
|
203
|
-
it "should return only the pacific event when searching -
|
204
|
-
Event.where("timestamp.zone" => "-
|
203
|
+
it "should return only the pacific event when searching -08:00" do
|
204
|
+
Event.where("timestamp.zone" => "-08:00").to_a.should == [@pacific_event]
|
205
205
|
end
|
206
206
|
|
207
207
|
end
|
data/spec/time_storage_spec.rb
CHANGED
@@ -58,7 +58,7 @@ describe "Mongoid::Metastamp::Time" do
|
|
58
58
|
|
59
59
|
[0, 12, 23].each do |hour|
|
60
60
|
|
61
|
-
["+00:00", "-
|
61
|
+
["+00:00", "-05:00", "-08:00", "+13:00"].each do |zone|
|
62
62
|
|
63
63
|
time_utc = Time.new(2011, 12, 31, hour, 0, 0, '-00:00')
|
64
64
|
time = Time.new(2011, 12, 31, hour, 0, 0, zone)
|
metadata
CHANGED
@@ -1,72 +1,59 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-metastamp
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Peter Gumeson
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-10-11 00:00:00 -07:00
|
12
|
+
date: 2012-02-27 00:00:00.000000000 -08:00
|
14
13
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
17
16
|
name: mongoid
|
18
|
-
|
19
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &2160882720 !ruby/object:Gem::Requirement
|
20
18
|
none: false
|
21
|
-
requirements:
|
19
|
+
requirements:
|
22
20
|
- - ~>
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version:
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.4'
|
25
23
|
type: :runtime
|
26
|
-
version_requirements: *id001
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bson_ext
|
29
24
|
prerelease: false
|
30
|
-
|
31
|
-
|
32
|
-
requirements:
|
33
|
-
- - ~>
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: "1.3"
|
36
|
-
type: :development
|
37
|
-
version_requirements: *id002
|
38
|
-
- !ruby/object:Gem::Dependency
|
25
|
+
version_requirements: *2160882720
|
26
|
+
- !ruby/object:Gem::Dependency
|
39
27
|
name: rake
|
40
|
-
|
41
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
28
|
+
requirement: &2160882220 !ruby/object:Gem::Requirement
|
42
29
|
none: false
|
43
|
-
requirements:
|
30
|
+
requirements:
|
44
31
|
- - ~>
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version:
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.9'
|
47
34
|
type: :development
|
48
|
-
version_requirements: *id003
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: rspec
|
51
35
|
prerelease: false
|
52
|
-
|
36
|
+
version_requirements: *2160882220
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
requirement: &2160881760 !ruby/object:Gem::Requirement
|
53
40
|
none: false
|
54
|
-
requirements:
|
41
|
+
requirements:
|
55
42
|
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version:
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '2.6'
|
58
45
|
type: :development
|
59
|
-
|
60
|
-
|
61
|
-
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2160881760
|
48
|
+
description: ! ' Provides Mongoid with enhanced meta-timestamps that store additional
|
49
|
+
parsed time metadata, allowing more powerful querying on specific time fields and
|
50
|
+
across normalized time zones. '
|
51
|
+
email:
|
62
52
|
- gumeson@gmail.com
|
63
53
|
executables: []
|
64
|
-
|
65
54
|
extensions: []
|
66
|
-
|
67
55
|
extra_rdoc_files: []
|
68
|
-
|
69
|
-
files:
|
56
|
+
files:
|
70
57
|
- .gitignore
|
71
58
|
- .rspec
|
72
59
|
- Gemfile
|
@@ -74,7 +61,6 @@ files:
|
|
74
61
|
- README.md
|
75
62
|
- Rakefile
|
76
63
|
- lib/mongoid-metastamp.rb
|
77
|
-
- lib/mongoid/core_ext.rb
|
78
64
|
- lib/mongoid/metastamp.rb
|
79
65
|
- lib/mongoid/metastamp/time.rb
|
80
66
|
- lib/mongoid/metastamp/version.rb
|
@@ -87,32 +73,29 @@ files:
|
|
87
73
|
has_rdoc: true
|
88
74
|
homepage: http://rubygems.org/gems/mongoid-metastamp
|
89
75
|
licenses: []
|
90
|
-
|
91
76
|
post_install_message:
|
92
77
|
rdoc_options: []
|
93
|
-
|
94
|
-
require_paths:
|
78
|
+
require_paths:
|
95
79
|
- lib
|
96
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
81
|
none: false
|
98
|
-
requirements:
|
99
|
-
- -
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version:
|
102
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
87
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
version:
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
108
92
|
requirements: []
|
109
|
-
|
110
93
|
rubyforge_project: mongoid-metastamp
|
111
94
|
rubygems_version: 1.6.2
|
112
95
|
signing_key:
|
113
96
|
specification_version: 3
|
114
97
|
summary: Store and query more useful information about your Mongoid timestamps.
|
115
|
-
test_files:
|
98
|
+
test_files:
|
116
99
|
- spec/models/event.rb
|
117
100
|
- spec/spec_helper.rb
|
118
101
|
- spec/time_compatibility_spec.rb
|
data/lib/mongoid/core_ext.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Mongoid #:nodoc
|
4
|
-
module Fields #:nodoc:
|
5
|
-
module Mappings #:nodoc:
|
6
|
-
|
7
|
-
def for(klass, foreign_key = false)
|
8
|
-
return Serializable::Object unless klass
|
9
|
-
if foreign_key
|
10
|
-
return "#{MODULE}::ForeignKeys::#{klass.to_s.demodulize}".constantize
|
11
|
-
end
|
12
|
-
begin
|
13
|
-
modules = "#{MODULE}::|BSON::|ActiveSupport::"
|
14
|
-
if match = klass.to_s.match(Regexp.new("^(#{ modules })?(\\w+)$"))
|
15
|
-
"#{MODULE}::#{match[2]}".constantize
|
16
|
-
else
|
17
|
-
klass.to_s.constantize
|
18
|
-
end
|
19
|
-
rescue NameError
|
20
|
-
klass
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|