mongoid_occurrence_views 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +19 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +11 -0
- data/Guardfile +5 -0
- data/README.md +136 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/mongoid_occurrence_views.rb +25 -0
- data/lib/mongoid_occurrence_views/create_mongodb_view.rb +25 -0
- data/lib/mongoid_occurrence_views/destroy_mongodb_view.rb +23 -0
- data/lib/mongoid_occurrence_views/event.rb +21 -0
- data/lib/mongoid_occurrence_views/event/create_expanded_occurrences_view.rb +34 -0
- data/lib/mongoid_occurrence_views/event/create_occurrences_ordering_view.rb +31 -0
- data/lib/mongoid_occurrence_views/event/create_view.rb +40 -0
- data/lib/mongoid_occurrence_views/event/has_occurrence_scopes.rb +32 -0
- data/lib/mongoid_occurrence_views/event/has_views_on_occurrences.rb +81 -0
- data/lib/mongoid_occurrence_views/event/occurrence.rb +122 -0
- data/lib/mongoid_occurrence_views/queries/occurs_between.rb +28 -0
- data/lib/mongoid_occurrence_views/queries/occurs_from.rb +22 -0
- data/lib/mongoid_occurrence_views/queries/occurs_on.rb +24 -0
- data/lib/mongoid_occurrence_views/queries/occurs_until.rb +22 -0
- data/lib/mongoid_occurrence_views/queries/order_by_end.rb +19 -0
- data/lib/mongoid_occurrence_views/queries/order_by_start.rb +19 -0
- data/lib/mongoid_occurrence_views/queries/query.rb +21 -0
- data/lib/mongoid_occurrence_views/version.rb +3 -0
- data/mongoid_occurrence_views.gemspec +36 -0
- metadata +263 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ec270d211cd1ad0bc58b60980d77f4defff948f5c8bd0d63db70f450f1f7d5c7
|
4
|
+
data.tar.gz: 2b351998c8815c1d1cd0aa7af2778e44e390f606cd35ae140bf9b246abc20bdb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f915e5edb172f9a21bdb48bd1442fbcc677716212b9314e6463b93b0f6f755481bdf9a690bce663f623968edc0f312b1643d6e9f568e1420519583bb5dd277d2
|
7
|
+
data.tar.gz: b818d09e3c18d21b994a7250cf785ad898822d3d134cdc68e57b3e7844e39935b68b9a1ef8f4eeb1e6ff781c7b1031368a0bd551e52110a3979324c8f98ccf90
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
script: 'bundle exec rake'
|
4
|
+
rvm:
|
5
|
+
- 2.5.1
|
6
|
+
services:
|
7
|
+
- mongodb
|
8
|
+
|
9
|
+
notifications:
|
10
|
+
email:
|
11
|
+
recipients:
|
12
|
+
- tomas.celizna@gmail.com
|
13
|
+
on_failure: change
|
14
|
+
on_success: never
|
15
|
+
|
16
|
+
matrix:
|
17
|
+
include:
|
18
|
+
- rvm: 2.5.1
|
19
|
+
env: MONGOID_VERSION=7
|
data/Gemfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in mongoid_occurrence_views.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
case version = ENV['MONGOID_VERSION'] || '~> 7.0'
|
9
|
+
when /7/ then gem 'mongoid', '~> 7.0'
|
10
|
+
else gem 'mongoid', version
|
11
|
+
end
|
data/Guardfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# Mongoid Occurrence Views
|
2
|
+
|
3
|
+
[](https://travis-ci.org/tomasc/mongoid_occurrence_views) [](http://badge.fury.io/rb/mongoid_occurrence_views) [](https://coveralls.io/r/tomasc/mongoid_occurrence_views)
|
4
|
+
|
5
|
+
By taking advantage of [Mongodb views](https://docs.mongodb.com/manual/core/views), this gem simplifies querying for events with multiple occurrences or a recurring schedule.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
* Mongoid 7.1+
|
10
|
+
* MongoDB 3.4+
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'mongoid_occurrence_views'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install mongoid_occurrence_views
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Occurrences
|
31
|
+
|
32
|
+
Define a Mongoid document class that will hold information about each occurrence.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class Occurrence
|
36
|
+
include Mongoid::Document
|
37
|
+
include MongoidOccurrenceViews::Event::Occurrence
|
38
|
+
|
39
|
+
embedded_in_event class_name: 'Event'
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
This will create the following fields on `Occurrence`:
|
44
|
+
|
45
|
+
* `dtstart`, (`DateTime`)
|
46
|
+
* `dtend` (`DateTime`)
|
47
|
+
* `schedule` (`MongoidIceCubeExtension::Schedule`)
|
48
|
+
|
49
|
+
And the `all_day` (`Boolean`) `attr_accessor`, which is useful for user-facing forms.
|
50
|
+
|
51
|
+
### Events
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
class Event
|
55
|
+
include Mongoid::Document
|
56
|
+
include MongoidOccurrenceViews::Event
|
57
|
+
|
58
|
+
embeds_many_occurrences class_name: 'Occurrence'
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
The `embeds_many_occurences` macro will setup an embedded relation that holds a definition of occurrences. For example:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
<Occurrence dtstart: …, dtend: …, schedule: …>
|
66
|
+
<Occurrence dtstart: …, dtend: …, schedule: …>
|
67
|
+
<Occurrence dtstart: …, dtend: …, schedule: …>
|
68
|
+
```
|
69
|
+
|
70
|
+
Before each validation callback, each occurrence will expand its definition as follows:
|
71
|
+
|
72
|
+
* multi-day occurrences are split into single-day occurrences
|
73
|
+
* recurring schedules are expanded into single-day occurrences
|
74
|
+
|
75
|
+
The following scopes are available for querying:
|
76
|
+
|
77
|
+
* `occurs_between(Time, Time)`
|
78
|
+
* `occurs_from(Time)`
|
79
|
+
* `occurs_on(Time)`
|
80
|
+
* `occurs_until(Time)`
|
81
|
+
|
82
|
+
And these scopes for ordering:
|
83
|
+
|
84
|
+
* `order_by_start(:asc / :desc)`
|
85
|
+
* `order_by_end(:asc / :desc)`
|
86
|
+
|
87
|
+
### Views & queries
|
88
|
+
|
89
|
+
The gem creates two views (virtual collections):
|
90
|
+
|
91
|
+
* `expanded_occurrences_view` for working with the expanded events
|
92
|
+
* `occurrences_ordering_view` for ordering the unexpanded events
|
93
|
+
|
94
|
+
#### Expanded Occurrences View
|
95
|
+
|
96
|
+
This view lists expanded events – meaning events expanded for each daily occurrence.
|
97
|
+
|
98
|
+
Use the `with_expanded_occurrences_view` method to query the expanded events:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
Event.with_expanded_occurrences_view do
|
102
|
+
Event.occurs_from(Time.zone.now).…
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
The `.with_expanded_occurrences_view` method is simply a syntactic sugar on top of Mongoid's `.with(collection: …)` method, which specifies the collection to be the expanded occurrences view (`event__expanded_occurrences_view`).
|
107
|
+
|
108
|
+
The view adds a `:_dtstart` and `:_dtend` fields to each `Event`.
|
109
|
+
|
110
|
+
#### Occurrences Ordering View
|
111
|
+
|
112
|
+
This view lists unexpanded events, circumnavigating Mongodb limitation for sorting by embedded documents. It adds `dtstart` field with a value coming from occurrence chronologically first, and `dtend` field with a value of occurrence chronologically last.
|
113
|
+
|
114
|
+
Use the `with_occurrences_ordering_view` method to order the unexpanded events.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
Event.with_occurrences_ordering_view do
|
118
|
+
Event.order_by_start(:asc)…
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
The `.with_occurrences_ordering_view` method is simply a syntactic sugar on top of Mongoid's `.with(collection: …)` method, which specifies the collection to be the expanded occurrences view (`event__expanded_occurrences_view`).
|
123
|
+
|
124
|
+
## Development
|
125
|
+
|
126
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
127
|
+
|
128
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
129
|
+
|
130
|
+
## Contributing
|
131
|
+
|
132
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/tomasc/mongoid_occurrence_views.
|
133
|
+
|
134
|
+
## License
|
135
|
+
|
136
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "mongoid_occurrence_views"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mongoid_occurrence_views/version'
|
2
|
+
|
3
|
+
require 'mongoid'
|
4
|
+
require 'mongoid_ice_cube_extension'
|
5
|
+
|
6
|
+
require 'mongoid_occurrence_views/create_mongodb_view'
|
7
|
+
require 'mongoid_occurrence_views/destroy_mongodb_view'
|
8
|
+
|
9
|
+
require 'mongoid_occurrence_views/event'
|
10
|
+
require 'mongoid_occurrence_views/event/occurrence'
|
11
|
+
|
12
|
+
require 'mongoid_occurrence_views/event/has_views_on_occurrences'
|
13
|
+
require 'mongoid_occurrence_views/event/has_occurrence_scopes'
|
14
|
+
|
15
|
+
require 'mongoid_occurrence_views/event/create_view'
|
16
|
+
require 'mongoid_occurrence_views/event/create_expanded_occurrences_view'
|
17
|
+
require 'mongoid_occurrence_views/event/create_occurrences_ordering_view'
|
18
|
+
|
19
|
+
require 'mongoid_occurrence_views/queries/query'
|
20
|
+
require 'mongoid_occurrence_views/queries/occurs_between'
|
21
|
+
require 'mongoid_occurrence_views/queries/occurs_from'
|
22
|
+
require 'mongoid_occurrence_views/queries/occurs_on'
|
23
|
+
require 'mongoid_occurrence_views/queries/occurs_until'
|
24
|
+
require 'mongoid_occurrence_views/queries/order_by_end'
|
25
|
+
require 'mongoid_occurrence_views/queries/order_by_start'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
class CreateMongodbView
|
3
|
+
def initialize(name:, collection:, pipeline:)
|
4
|
+
@name = name
|
5
|
+
@collection = collection
|
6
|
+
@pipeline = pipeline
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.call(*args)
|
10
|
+
new(*args).call
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
Mongoid.clients.each do |client_name, _|
|
15
|
+
client = Mongoid.client(client_name)
|
16
|
+
next if client.collections.map(&:name).include?(name)
|
17
|
+
client.command(create: name, viewOn: collection, pipeline: pipeline)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :name, :collection, :pipeline
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
class DestroyMongodbView
|
3
|
+
def initialize(name:)
|
4
|
+
@name = name
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.call(*args)
|
8
|
+
new(*args).call
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Mongoid.clients.each do |client_name, _|
|
13
|
+
client = Mongoid.client(client_name)
|
14
|
+
next unless client.collections.map(&:name).include?(name)
|
15
|
+
client.command(drop: name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :name
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
include HasViewsOnOccurrences
|
6
|
+
include HasOccurrenceScopes
|
7
|
+
end
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def embeds_many_occurrences(options = {})
|
13
|
+
embeds_many :occurrences, class_name: options.fetch(:class_name)
|
14
|
+
accepts_nested_attributes_for :occurrences, allow_destroy: true, reject_if: :all_blank
|
15
|
+
|
16
|
+
CreateExpandedOccurrencesView.call(self) unless embedded?
|
17
|
+
CreateOccurrencesOrderingView.call(self) unless embedded?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
class CreateExpandedOccurrencesView < CreateView
|
4
|
+
def view_name
|
5
|
+
klass.expanded_occurrences_view_name
|
6
|
+
end
|
7
|
+
|
8
|
+
def pipeline
|
9
|
+
[add_fields,
|
10
|
+
unwind_associations_to_parent,
|
11
|
+
add_datetime_fields].flatten
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def add_fields
|
17
|
+
{ '$addFields': { "_#{occurrence_relation_chain.first}": "$#{occurrence_relation_chain.first}" } }
|
18
|
+
end
|
19
|
+
|
20
|
+
def unwind_associations_to_parent
|
21
|
+
occurrence_relations_chained.map do |chain|
|
22
|
+
{ '$unwind': "$_#{chain}" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_datetime_fields
|
27
|
+
{ '$addFields': {
|
28
|
+
'_dtstart': "$_#{occurrence_relations_chained.last}.ds",
|
29
|
+
'_dtend': "$_#{occurrence_relations_chained.last}.de",
|
30
|
+
} }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
class CreateOccurrencesOrderingView < CreateView
|
4
|
+
def view_name
|
5
|
+
klass.occurrences_ordering_view_name
|
6
|
+
end
|
7
|
+
|
8
|
+
def pipeline
|
9
|
+
[add_fields].flatten
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def add_fields
|
15
|
+
{ '$addFields': { '_dtstart': order_dtstart_field, '_dtend': order_dtend_field } }
|
16
|
+
end
|
17
|
+
|
18
|
+
def order_dtstart_field
|
19
|
+
min = "$#{occurrence_relations_chained.last}.ds"
|
20
|
+
occurrence_relations_chained.length.times { min = { '$min': min } }
|
21
|
+
min
|
22
|
+
end
|
23
|
+
|
24
|
+
def order_dtend_field
|
25
|
+
max = "$#{occurrence_relations_chained.last}.de"
|
26
|
+
occurrence_relations_chained.length.times { max = { '$max': max } }
|
27
|
+
max
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
class CreateView
|
4
|
+
delegate(
|
5
|
+
:occurrence_relations_chained,
|
6
|
+
:occurrence_relation_chain,
|
7
|
+
|
8
|
+
to: :klass
|
9
|
+
)
|
10
|
+
|
11
|
+
def initialize(klass)
|
12
|
+
@klass = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.call(*args)
|
16
|
+
new(*args).call
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
CreateMongodbView.call(
|
21
|
+
name: view_name,
|
22
|
+
collection: klass.collection.name,
|
23
|
+
pipeline: pipeline
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def pipeline
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
def view_name
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :klass
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
module HasOccurrenceScopes
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.class_eval do
|
7
|
+
scope :occurs_between, ->(dtstart, dtend, dtstart_field = dtstart_query_field, dtend_field = dtend_query_field) { MongoidOccurrenceViews::Queries::OccursBetween.criteria(criteria, dtstart, dtend, dtstart_field: dtstart_field, dtend_field: dtend_field) }
|
8
|
+
scope :occurs_from, ->(date_time, dtstart_field = dtstart_query_field) { MongoidOccurrenceViews::Queries::OccursFrom.criteria(criteria, date_time, dtstart_field: dtstart_field) }
|
9
|
+
scope :occurs_on, -> (date_time, dtstart_field = dtstart_query_field, dtend_field = dtend_query_field) { MongoidOccurrenceViews::Queries::OccursOn.criteria(criteria, date_time, dtstart_field: dtstart_field, dtend_field: dtend_field) }
|
10
|
+
scope :occurs_until, ->(date_time, dtend_field = dtend_query_field) { MongoidOccurrenceViews::Queries::OccursUntil.criteria(criteria, date_time, dtend_field: dtend_field) }
|
11
|
+
|
12
|
+
scope :order_by_start, ->(order = :asc, dtstart_field = dtstart_query_field) { MongoidOccurrenceViews::Queries::OrderByStart.criteria(criteria, order, dtstart_field: dtstart_field) }
|
13
|
+
scope :order_by_end, ->(order = :asc, dtend_field = dtend_query_field) { MongoidOccurrenceViews::Queries::OrderByEnd.criteria(criteria, order, dtend_field: dtend_field) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def dtstart_query_field
|
19
|
+
within_view? ? :_dtstart : :"#{occurrence_relations_chained.last}.ds"
|
20
|
+
end
|
21
|
+
|
22
|
+
def dtend_query_field
|
23
|
+
within_view? ? :_dtend : :"#{occurrence_relations_chained.last}.de"
|
24
|
+
end
|
25
|
+
|
26
|
+
def within_view?
|
27
|
+
collection.name =~ /#{MongoidOccurrenceViews::Event::HasViewsOnOccurrences::EXPANDED_VIEW_NAME_SUFFIX}|#{MongoidOccurrenceViews::Event::HasViewsOnOccurrences::ORDERING_VIEW_NAME_SUFFIX}/
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
module HasViewsOnOccurrences
|
4
|
+
ORDERING_VIEW_NAME_SUFFIX = 'occurrences_ordering_view'.freeze
|
5
|
+
EXPANDED_VIEW_NAME_SUFFIX = 'expanded_occurrences_view'.freeze
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
def dtstart
|
12
|
+
return unless self.class.within_view?
|
13
|
+
DateTime.demongoize(self[:_dtstart])
|
14
|
+
end
|
15
|
+
|
16
|
+
def dtend
|
17
|
+
return unless self.class.within_view?
|
18
|
+
DateTime.demongoize(self[:_dtend])
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def occurrences_ordering_view_name
|
23
|
+
[collection.name, ORDERING_VIEW_NAME_SUFFIX].join('__').freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def expanded_occurrences_view_name
|
27
|
+
[collection.name, EXPANDED_VIEW_NAME_SUFFIX].join('__').freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_expanded_occurrences_view(&block)
|
31
|
+
with_occurrences_view(expanded: true, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_occurrences_ordering_view(&block)
|
35
|
+
with_occurrences_view(expanded: false, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def with_occurrences_view(options = {}, &block)
|
39
|
+
expanded = options.delete(:expanded) { |_| true }
|
40
|
+
options[:collection] ||= expanded ? expanded_occurrences_view_name : occurrences_ordering_view_name
|
41
|
+
criteria.with(options, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def occurrence_relations_chained
|
45
|
+
occurrence_relation_chain.each_with_index.map do |_, i|
|
46
|
+
occurrence_relation_chain[0..i].join('.')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def occurrence_relation_chain
|
51
|
+
return occurrence_relation_names unless event_relations.present?
|
52
|
+
[event_relations.first.store_as, occurrence_relation_names].flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
def event_relations
|
56
|
+
return unless self.relations.present?
|
57
|
+
self.relations.values.select { |rel| is_event_relation?(rel) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def is_event_relation?(rel)
|
61
|
+
relation_class_name = rel.options[:class_name]
|
62
|
+
return false unless relation_class_name.present?
|
63
|
+
return true if event_class_names.include?(relation_class_name)
|
64
|
+
return unless relation_class = relation_class_name.safe_constantize
|
65
|
+
event_superclasses = event_class_names.map { |cn| cn.safe_constantize.ancestors }.flatten
|
66
|
+
event_superclasses.include? relation_class
|
67
|
+
end
|
68
|
+
|
69
|
+
def event_class_names
|
70
|
+
ObjectSpace.each_object(Class).select do |cls|
|
71
|
+
cls.included_modules.include?(MongoidOccurrenceViews::Event)
|
72
|
+
end.map(&:to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
def occurrence_relation_names
|
76
|
+
%w[occurrences daily_occurrences]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Event
|
3
|
+
module Occurrence
|
4
|
+
SCHEDULE_DURATION = 1.year
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.include MongoidOccurrenceViews::Event::HasOccurrenceScopes
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def embedded_in_event(options = {})
|
13
|
+
field :dtstart, type: DateTime
|
14
|
+
field :dtend, type: DateTime
|
15
|
+
|
16
|
+
field :schedule, type: MongoidIceCubeExtension::Schedule
|
17
|
+
field :schedule_dtend, type: Time
|
18
|
+
|
19
|
+
embedded_in :event, class_name: options.fetch(:class_name, nil)
|
20
|
+
embeds_many :daily_occurrences, class_name: 'MongoidOccurrenceViews::Event::Occurrence::DailyOccurrence', order: :dtstart.asc
|
21
|
+
|
22
|
+
validates_presence_of :dtstart
|
23
|
+
validates_presence_of :dtend
|
24
|
+
|
25
|
+
before_validation :nil_schedule, unless: :recurring?
|
26
|
+
|
27
|
+
after_validation :adjust_dates_for_all_day, if: :changed?
|
28
|
+
after_validation :assign_daily_occurrences, if: :changed?
|
29
|
+
end
|
30
|
+
|
31
|
+
def dtstart_query_field
|
32
|
+
:"daily_occurrences.ds"
|
33
|
+
end
|
34
|
+
|
35
|
+
def dtend_query_field
|
36
|
+
:"daily_occurrences.de"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def all_day
|
41
|
+
return unless dtstart.present?
|
42
|
+
return unless dtend.present?
|
43
|
+
|
44
|
+
@all_day ||= dtstart == dtstart.beginning_of_day && dtend == dtend.end_of_day
|
45
|
+
end
|
46
|
+
alias all_day? all_day
|
47
|
+
|
48
|
+
def all_day=(val)
|
49
|
+
@all_day = [true, 'true', 1, '1'].include?(val)
|
50
|
+
end
|
51
|
+
|
52
|
+
def recurring?
|
53
|
+
schedule.present?
|
54
|
+
end
|
55
|
+
|
56
|
+
def schedule_dtend
|
57
|
+
read_attribute(:schedule_dtend) || (dtstart.try(:to_time) || Time.now) + SCHEDULE_DURATION
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def nil_schedule
|
63
|
+
self.schedule = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def adjust_dates_for_all_day
|
67
|
+
return unless all_day?
|
68
|
+
|
69
|
+
self.dtstart = dtstart.beginning_of_day
|
70
|
+
self.dtend = dtend.end_of_day
|
71
|
+
end
|
72
|
+
|
73
|
+
def assign_daily_occurrences
|
74
|
+
return unless dtstart_changed? || dtend_changed? || schedule_changed? || schedule_dtend_changed?
|
75
|
+
self.daily_occurrences = daily_occurrences_from_schedule + daily_occurrences_from_date_range
|
76
|
+
end
|
77
|
+
|
78
|
+
def daily_occurrences_from_schedule
|
79
|
+
return [] unless recurring?
|
80
|
+
|
81
|
+
schedule.occurrences(schedule_dtend).map do |occurrence|
|
82
|
+
relations['daily_occurrences'].klass.new(
|
83
|
+
dtstart: occurrence.start_time,
|
84
|
+
dtend: occurrence.end_time.change(hour: dtend.hour, min: dtend.minute)
|
85
|
+
)
|
86
|
+
end.compact
|
87
|
+
end
|
88
|
+
|
89
|
+
def daily_occurrences_from_date_range
|
90
|
+
return [] if recurring?
|
91
|
+
date_range = Range.new(dtstart.to_date, dtend.to_date)
|
92
|
+
is_single_day = (date_range.first == date_range.last)
|
93
|
+
|
94
|
+
date_range.map do |date|
|
95
|
+
occurence_dtstart = is_single_day || date == date_range.first ? dtstart : date.beginning_of_day
|
96
|
+
occurence_dtend = is_single_day || date == date_range.last ? dtend : date.end_of_day
|
97
|
+
|
98
|
+
relations['daily_occurrences'].klass.new(
|
99
|
+
dtstart: occurence_dtstart,
|
100
|
+
dtend: occurence_dtend
|
101
|
+
)
|
102
|
+
end.compact
|
103
|
+
end
|
104
|
+
|
105
|
+
class DailyOccurrence
|
106
|
+
include Mongoid::Document
|
107
|
+
|
108
|
+
# alias fields to keep document size small
|
109
|
+
field :ds, as: :dtstart, type: DateTime
|
110
|
+
field :de, as: :dtend, type: DateTime
|
111
|
+
|
112
|
+
def all_day
|
113
|
+
return unless dtstart.present?
|
114
|
+
return unless dtend.present?
|
115
|
+
|
116
|
+
dtstart == dtstart.beginning_of_day && dtend == dtend.end_of_day
|
117
|
+
end
|
118
|
+
alias all_day? all_day
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OccursBetween < Query
|
4
|
+
def initialize(base_criteria, dtstart, dtend, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@dtstart = dtstart
|
7
|
+
@dtend = dtend
|
8
|
+
@dtstart_field = options.fetch(:dtstart_field)
|
9
|
+
@dtend_field = options.fetch(:dtend_field)
|
10
|
+
end
|
11
|
+
|
12
|
+
def criteria
|
13
|
+
_dtstart = dtstart.beginning_of_day if dtstart.instance_of?(Date)
|
14
|
+
_dtstart = dtstart.utc
|
15
|
+
|
16
|
+
_dtend = dtend.end_of_day if dtend.instance_of?(Date)
|
17
|
+
_dtend = dtend.utc
|
18
|
+
|
19
|
+
base_criteria.lte(dtstart_field => dtend.to_datetime)
|
20
|
+
.gte(dtend_field => dtstart.to_datetime)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :dtstart, :dtend, :dtstart_field, :dtend_field
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OccursFrom < Query
|
4
|
+
def initialize(base_criteria, date_time, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@date_time = date_time
|
7
|
+
@dtstart_field = options.fetch(:dtstart_field)
|
8
|
+
end
|
9
|
+
|
10
|
+
def criteria
|
11
|
+
_date_time = date_time.end_of_day if date_time.instance_of?(Date)
|
12
|
+
_date_time = date_time.utc
|
13
|
+
|
14
|
+
base_criteria.gte(dtstart_field => _date_time)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :date_time, :dtstart_field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OccursOn < Query
|
4
|
+
def initialize(base_criteria, date_time, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@date_time = date_time
|
7
|
+
@dtstart_field = options.fetch(:dtstart_field)
|
8
|
+
@dtend_field = options.fetch(:dtend_field)
|
9
|
+
end
|
10
|
+
|
11
|
+
def criteria
|
12
|
+
_date_time = date_time.beginning_of_day if date_time.instance_of?(Date)
|
13
|
+
_date_time = date_time.utc
|
14
|
+
|
15
|
+
base_criteria.lte(dtstart_field => _date_time)
|
16
|
+
.gte(dtend_field => _date_time)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :date_time, :dtstart_field, :dtend_field
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OccursUntil < Query
|
4
|
+
def initialize(base_criteria, date_time, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@date_time = date_time
|
7
|
+
@dtend_field = options.fetch(:dtend_field)
|
8
|
+
end
|
9
|
+
|
10
|
+
def criteria
|
11
|
+
_date_time = date_time.beginning_of_day if date_time.instance_of?(Date)
|
12
|
+
_date_time = date_time.utc
|
13
|
+
|
14
|
+
base_criteria.lte(dtend_field => _date_time)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :date_time, :dtend_field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OrderByEnd < Query
|
4
|
+
def initialize(base_criteria, order, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@order = order
|
7
|
+
@dtend_field = options.fetch(:dtend_field)
|
8
|
+
end
|
9
|
+
|
10
|
+
def criteria
|
11
|
+
base_criteria.order_by(dtend_field => order)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :order, :dtend_field
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class OrderByStart < Query
|
4
|
+
def initialize(base_criteria, order, options = {})
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
@order = order
|
7
|
+
@dtstart_field = options.fetch(:dtstart_field)
|
8
|
+
end
|
9
|
+
|
10
|
+
def criteria
|
11
|
+
base_criteria.order_by(dtstart_field => order)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :order, :dtstart_field
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MongoidOccurrenceViews
|
2
|
+
module Queries
|
3
|
+
class Query
|
4
|
+
def initialize(base_criteria)
|
5
|
+
@base_criteria = base_criteria
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.criteria(*args)
|
9
|
+
new(*args).criteria
|
10
|
+
end
|
11
|
+
|
12
|
+
def criteria
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :base_criteria
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'mongoid_occurrence_views/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'mongoid_occurrence_views'
|
7
|
+
spec.version = MongoidOccurrenceViews::VERSION
|
8
|
+
spec.authors = ['Tomas Celizna', 'Asger Behncke Jacobsen']
|
9
|
+
spec.email = ['tomas.celizna@gmail.com', 'a@asgerbehnckejacobsen.dk']
|
10
|
+
|
11
|
+
spec.summary = "Makes one's life easier when working with events that have multiple occurrences, or a recurring schedule."
|
12
|
+
spec.homepage = 'https://github.com/tomasc/mongoid_occurrence_views'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'ice_cube'
|
23
|
+
spec.add_dependency 'mongoid', '>= 7.0.2', '< 8'
|
24
|
+
spec.add_dependency 'mongoid_ice_cube_extension', '>= 0.1.1'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'activesupport', '> 3.0'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
28
|
+
spec.add_development_dependency 'coveralls'
|
29
|
+
spec.add_development_dependency 'database_cleaner'
|
30
|
+
spec.add_development_dependency 'factory_bot', '~> 4.0'
|
31
|
+
spec.add_development_dependency 'guard'
|
32
|
+
spec.add_development_dependency 'guard-minitest'
|
33
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
34
|
+
spec.add_development_dependency 'minitest-implicit-subject'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongoid_occurrence_views
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tomas Celizna
|
8
|
+
- Asger Behncke Jacobsen
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2018-10-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ice_cube
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: mongoid
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 7.0.2
|
35
|
+
- - "<"
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '8'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 7.0.2
|
45
|
+
- - "<"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '8'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: mongoid_ice_cube_extension
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.1
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.1.1
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activesupport
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: bundler
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.16'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.16'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: coveralls
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: database_cleaner
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: factory_bot
|
120
|
+
requirement: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '4.0'
|
125
|
+
type: :development
|
126
|
+
prerelease: false
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '4.0'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: guard
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
type: :development
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
- !ruby/object:Gem::Dependency
|
147
|
+
name: guard-minitest
|
148
|
+
requirement: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
type: :development
|
154
|
+
prerelease: false
|
155
|
+
version_requirements: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
- !ruby/object:Gem::Dependency
|
161
|
+
name: minitest
|
162
|
+
requirement: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '5.0'
|
167
|
+
type: :development
|
168
|
+
prerelease: false
|
169
|
+
version_requirements: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '5.0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: minitest-implicit-subject
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
type: :development
|
182
|
+
prerelease: false
|
183
|
+
version_requirements: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
- !ruby/object:Gem::Dependency
|
189
|
+
name: rake
|
190
|
+
requirement: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '10.0'
|
195
|
+
type: :development
|
196
|
+
prerelease: false
|
197
|
+
version_requirements: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '10.0'
|
202
|
+
description:
|
203
|
+
email:
|
204
|
+
- tomas.celizna@gmail.com
|
205
|
+
- a@asgerbehnckejacobsen.dk
|
206
|
+
executables: []
|
207
|
+
extensions: []
|
208
|
+
extra_rdoc_files: []
|
209
|
+
files:
|
210
|
+
- ".gitignore"
|
211
|
+
- ".travis.yml"
|
212
|
+
- CHANGELOG.md
|
213
|
+
- Gemfile
|
214
|
+
- Guardfile
|
215
|
+
- README.md
|
216
|
+
- Rakefile
|
217
|
+
- bin/console
|
218
|
+
- bin/setup
|
219
|
+
- lib/mongoid_occurrence_views.rb
|
220
|
+
- lib/mongoid_occurrence_views/create_mongodb_view.rb
|
221
|
+
- lib/mongoid_occurrence_views/destroy_mongodb_view.rb
|
222
|
+
- lib/mongoid_occurrence_views/event.rb
|
223
|
+
- lib/mongoid_occurrence_views/event/create_expanded_occurrences_view.rb
|
224
|
+
- lib/mongoid_occurrence_views/event/create_occurrences_ordering_view.rb
|
225
|
+
- lib/mongoid_occurrence_views/event/create_view.rb
|
226
|
+
- lib/mongoid_occurrence_views/event/has_occurrence_scopes.rb
|
227
|
+
- lib/mongoid_occurrence_views/event/has_views_on_occurrences.rb
|
228
|
+
- lib/mongoid_occurrence_views/event/occurrence.rb
|
229
|
+
- lib/mongoid_occurrence_views/queries/occurs_between.rb
|
230
|
+
- lib/mongoid_occurrence_views/queries/occurs_from.rb
|
231
|
+
- lib/mongoid_occurrence_views/queries/occurs_on.rb
|
232
|
+
- lib/mongoid_occurrence_views/queries/occurs_until.rb
|
233
|
+
- lib/mongoid_occurrence_views/queries/order_by_end.rb
|
234
|
+
- lib/mongoid_occurrence_views/queries/order_by_start.rb
|
235
|
+
- lib/mongoid_occurrence_views/queries/query.rb
|
236
|
+
- lib/mongoid_occurrence_views/version.rb
|
237
|
+
- mongoid_occurrence_views.gemspec
|
238
|
+
homepage: https://github.com/tomasc/mongoid_occurrence_views
|
239
|
+
licenses:
|
240
|
+
- MIT
|
241
|
+
metadata: {}
|
242
|
+
post_install_message:
|
243
|
+
rdoc_options: []
|
244
|
+
require_paths:
|
245
|
+
- lib
|
246
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
252
|
+
requirements:
|
253
|
+
- - ">="
|
254
|
+
- !ruby/object:Gem::Version
|
255
|
+
version: '0'
|
256
|
+
requirements: []
|
257
|
+
rubyforge_project:
|
258
|
+
rubygems_version: 2.7.6
|
259
|
+
signing_key:
|
260
|
+
specification_version: 4
|
261
|
+
summary: Makes one's life easier when working with events that have multiple occurrences,
|
262
|
+
or a recurring schedule.
|
263
|
+
test_files: []
|