rooftop-rails-events 0.1.9
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/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +154 -0
- data/Rakefile +2 -0
- data/app/controllers/concerns/rooftop/rails/events/event_collections.rb +88 -0
- data/app/controllers/concerns/rooftop/rails/events/event_handler.rb +49 -0
- data/app/controllers/concerns/rooftop/rails/events/event_search.rb +10 -0
- data/app/models/concerns/rooftop/rails/events/booking_information.rb +22 -0
- data/app/models/concerns/rooftop/rails/events/cache.rb +44 -0
- data/app/models/concerns/rooftop/rails/events/instance_cache.rb +76 -0
- data/app/models/concerns/rooftop/rails/events/scopes.rb +48 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rooftop/rails/events.rb +14 -0
- data/lib/rooftop/rails/events/decorators.rb +18 -0
- data/lib/rooftop/rails/events/decorators/cast.rb +25 -0
- data/lib/rooftop/rails/events/decorators/content.rb +21 -0
- data/lib/rooftop/rails/events/decorators/event_detail_decorator.rb +142 -0
- data/lib/rooftop/rails/events/decorators/instance_decorator.rb +63 -0
- data/lib/rooftop/rails/events/decorators/media.rb +114 -0
- data/lib/rooftop/rails/events/decorators/person_decorator.rb +47 -0
- data/lib/rooftop/rails/events/decorators/reviews.rb +33 -0
- data/lib/rooftop/rails/events/decorators/times.rb +39 -0
- data/lib/rooftop/rails/events/engine.rb +31 -0
- data/lib/rooftop/rails/events/instance_decorators.rb +13 -0
- data/lib/rooftop/rails/events/version.rb +7 -0
- data/rooftop-rails-events.gemspec +28 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 43c3a9fa04042ebd6c88977baa161e2f99554620
|
4
|
+
data.tar.gz: dae897de59297fbf2ef58ed85984d44d1497a2db
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b232cf857b16de7483e1ba8bb02223b3a055bccfab23575c1d21d5c8489236d0962e441cebe8f5dda4a256f674dc622e4519ea011acc2d91e53455881f6f322f
|
7
|
+
data.tar.gz: cff98c0085dd4f4e82d775c45fde94566af04a69eb47e28c8c16a46fdf44a00e47dab48ef713d13fbeef063d9896e9ebf515b899f43a39cae972e2aa78248738
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Ed Jones
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# Rooftop::Rails::Events
|
2
|
+
|
3
|
+
A library to make it super-easy to integrate events from [Rooftop CMS](https://www.rooftopcms.com) into your Rails site.
|
4
|
+
|
5
|
+
## What's included
|
6
|
+
A bit of a mix of stuff, and all work in progress. Here's a flavour:
|
7
|
+
|
8
|
+
## Controller Mixins
|
9
|
+
You need to `include` these yourself.
|
10
|
+
|
11
|
+
### Rooftop::Rails::Events::EventHandler
|
12
|
+
A mixin for a controller which handles events. It has methods for show(), instances() and book_instance() which get the event from Rooftop for you.
|
13
|
+
|
14
|
+
In the simplest form, you can just include this in your controller
|
15
|
+
|
16
|
+
```
|
17
|
+
class EventsController < ApplicationController
|
18
|
+
include Rooftop::Rails::Events::EventHandler
|
19
|
+
end
|
20
|
+
````
|
21
|
+
|
22
|
+
But each method yields to a block so you can do other stuff if you want. Here's a more representative EventsController from a real project:
|
23
|
+
|
24
|
+
```
|
25
|
+
class EventsController < ApplicationController
|
26
|
+
include Rooftop::Rails::Events::EventHandler
|
27
|
+
decorates_assigned :events, :event, with: EventDecorator
|
28
|
+
layout :determine_layout
|
29
|
+
|
30
|
+
def instances
|
31
|
+
# Pass a block into the EventHandler mixin's method, which is yielded to at the end of the method
|
32
|
+
super do
|
33
|
+
# If the event has an external ticketing url, redirect to it instead of rendering a list of instances
|
34
|
+
# n.b. pretty obviously you'll need to define has_external_ticketing_url?() and external_ticketing_url() on your model
|
35
|
+
if @event.has_external_ticketing_url?
|
36
|
+
redirect_to @event.external_ticketing_url and return
|
37
|
+
end
|
38
|
+
|
39
|
+
# If the event only has 1 instance, it seems a bit mean to list that instance and make the user click again; go straight to the book_instance method
|
40
|
+
if @event.instances.count == 1
|
41
|
+
redirect_to action: :book_instance, instance_id: @event.instances.first.meta_attributes[:spektrix_id] and return
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def determine_layout
|
49
|
+
case action_name.to_sym
|
50
|
+
when :show
|
51
|
+
"templates/event_detail"
|
52
|
+
when :instances
|
53
|
+
"templates/instance_list"
|
54
|
+
when :book_instance
|
55
|
+
"templates/iframe_wide"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
## Model Mixins
|
62
|
+
These are `include`d automatically when you use this gem.
|
63
|
+
|
64
|
+
|
65
|
+
### Rooftop::Rails::Events::Cache
|
66
|
+
A mixin added to the Rooftop::Events::Event to cache / expire it.
|
67
|
+
|
68
|
+
### Rooftop::Rails::Events::InstanceCache
|
69
|
+
The same as `Rooftop::Rails::Events::Cache` but for instances. Allows you to receive a webhook for just an instance and be able to clear the cache for its associated `Event`.
|
70
|
+
|
71
|
+
### Rooftop::Rails::Events::Scopes
|
72
|
+
Handy scopes for dealing with events - finding after a date, between dates, in the future etc.
|
73
|
+
|
74
|
+
## Object Decorators
|
75
|
+
We use a lot of [Draper](https://github.com/drapergem/draper) as our decorator pattern at [Error Agency](https://error.agency). So there are some mixins you add to your EventDecorator to provide utility methods for use in views.
|
76
|
+
|
77
|
+
```
|
78
|
+
#in your project
|
79
|
+
class EventDecorator < Draper::Decorator
|
80
|
+
include Rooftop::Rails::Events::Decorators
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
## Controller mixin for Event collections
|
85
|
+
The standard pattern we've found works well for Rooftop is to have a PagesController with mixins which check the template of the page you're rendering, and makes requests to get collections of objects you'll need.
|
86
|
+
|
87
|
+
```
|
88
|
+
class PagesController < ApplicationController
|
89
|
+
include Rooftop::Rails::Events::EventCollections
|
90
|
+
end
|
91
|
+
```
|
92
|
+
You get a bunch of stuff for free with this:
|
93
|
+
|
94
|
+
* Rooftop events in the future will be returned as a collection called @events by default
|
95
|
+
* if you pass in query params, you can filter these:
|
96
|
+
* `q` will do a free-text search
|
97
|
+
* `from` will take an dd-mm-yyyy date string and return things happening on or after that date
|
98
|
+
* `to` will work likewise, in reverse
|
99
|
+
|
100
|
+
### Customising querystring filters
|
101
|
+
You might want to filter by something else. That's relatively easy.
|
102
|
+
|
103
|
+
```
|
104
|
+
class PagesController < ApplicationController
|
105
|
+
include Rooftop::Rails::Events::EventCollections
|
106
|
+
self.add_event_filter :genre, ->(events,params) {
|
107
|
+
# add something here which returns a collection when genre is passed in, for example
|
108
|
+
# very important - you must return something here
|
109
|
+
if params[:genre].present?
|
110
|
+
events.with_genre(params[:genre])
|
111
|
+
else
|
112
|
+
events
|
113
|
+
end
|
114
|
+
}
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
## Installation
|
121
|
+
|
122
|
+
Add this line to your application's Gemfile:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
gem 'rooftop-rails-events'
|
126
|
+
```
|
127
|
+
|
128
|
+
And then execute:
|
129
|
+
|
130
|
+
$ bundle
|
131
|
+
|
132
|
+
Or install it yourself as:
|
133
|
+
|
134
|
+
$ gem install rooftop-rails-events
|
135
|
+
|
136
|
+
## Usage
|
137
|
+
|
138
|
+
TODO: Write usage instructions here
|
139
|
+
|
140
|
+
## Development
|
141
|
+
|
142
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
143
|
+
|
144
|
+
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).
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rooftop-rails-events. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
149
|
+
|
150
|
+
|
151
|
+
## License
|
152
|
+
|
153
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
154
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
# A mixin for your PagesController, to get events based on your page template. If the appropriate template is present in the response for a page from Rooftop, we generate an @events instance var with the events. @events is filtered according to some basic things like to and from date, if the params are present.
|
5
|
+
module EventCollections
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
before_action :get_index_events, only: :show, if: :template_matches?
|
10
|
+
end
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
attr_reader :event_index_template, :event_filters, :filter_keys
|
14
|
+
def event_index_template=(template)
|
15
|
+
@event_index_template = template.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# A method to allow us to filter on extra things from the command line (e.g. genre)
|
19
|
+
# To use in your controller:
|
20
|
+
# self.add_event_filter :genre, ->(events) {
|
21
|
+
# return the matching set here
|
22
|
+
# }
|
23
|
+
|
24
|
+
def add_event_filter(key,filter)
|
25
|
+
if filter.is_a?(Proc)
|
26
|
+
@filter_keys ||= []
|
27
|
+
@event_filters ||= []
|
28
|
+
@filter_keys << key
|
29
|
+
@event_filters << filter
|
30
|
+
else
|
31
|
+
raise ArgumentError, "add_event_filter takes a proc which is evaluated in the filter_events method, and a params key to check for"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def template_matches?
|
38
|
+
self.class.event_index_template.present? && defined?(@page) && @page.template.present? && @page.template.underscore == self.class.event_index_template
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_index_events
|
42
|
+
@events = filter_events(Rooftop::Events::Event.in_future).sort_by {|e| e.event_instance_dates[:first]} rescue []
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_filter_keys?
|
46
|
+
fixed_filter_keys = ["from", "to", "q"]
|
47
|
+
self.class.filter_keys ||= []
|
48
|
+
all_filter_keys = fixed_filter_keys + self.class.filter_keys.collect(&:to_s)
|
49
|
+
(params.keys & all_filter_keys).any? && all_filter_keys.collect {|k| params[k].present?}.any?
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter_events(events)
|
53
|
+
return events unless has_filter_keys?
|
54
|
+
|
55
|
+
# Build a collection of collections, which we will intersect to get only ones which match all
|
56
|
+
all_match = []
|
57
|
+
|
58
|
+
|
59
|
+
if params[:from].present? && params[:to].present?
|
60
|
+
from = DateTime.parse(params[:from]) rescue DateTime.now
|
61
|
+
to = DateTime.parse(params[:to]) rescue DateTime.now
|
62
|
+
all_match << events.showing_between(from,to)
|
63
|
+
elsif params[:from].present?
|
64
|
+
from = DateTime.parse(params[:from]) rescue DateTime.now
|
65
|
+
all_match << events.showing_on(from)
|
66
|
+
end
|
67
|
+
|
68
|
+
# free-text search
|
69
|
+
if params[:q].present?
|
70
|
+
all_match << events.matching_query(params[:q])
|
71
|
+
end
|
72
|
+
|
73
|
+
# Iterate over any other filters supplied in procs
|
74
|
+
if self.class.event_filters.present?
|
75
|
+
self.class.event_filters.each do |filter|
|
76
|
+
all_match << filter.call(events, params)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# intersect all the alls
|
81
|
+
all_match.inject(:&)
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module EventHandler
|
5
|
+
# A module for showing an event and listing event instances. Note that we don't have an index endpoint in here - for that we use a template in the pages controller, and a mixin to get a collection of events if you're hitting that template. See Rooftop::Rails::Events::EventCollections for that.
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def show
|
9
|
+
@event = Rooftop::Events::Event.where(
|
10
|
+
slug: params[:id],
|
11
|
+
per_page: 1,
|
12
|
+
include_embedded_resources: true,
|
13
|
+
instances_per_page: -1,
|
14
|
+
no_filter: [
|
15
|
+
:include_embedded_resources,
|
16
|
+
:instances_per_page
|
17
|
+
]).first
|
18
|
+
if @event.nil?
|
19
|
+
raise Rooftop::RecordNotFoundError, "No event with slug #{params[:id]} found"
|
20
|
+
end
|
21
|
+
|
22
|
+
@instances = @event.embedded_instances
|
23
|
+
|
24
|
+
yield if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def instances
|
28
|
+
@event = Rooftop::Events::Event.where(slug: params[:event_id]).first
|
29
|
+
|
30
|
+
@instances = Rooftop::Events::Instance.all(_event_id: @event.id, include_embedded_resources: true).sort_by {|i| DateTime.parse(i.meta_attributes[:availability][:starts_at])}.to_a.reject! {|e| DateTime.parse(e.meta_attributes[:availability][:starts_at]) < DateTime.now}
|
31
|
+
|
32
|
+
@event_details = EventDetailDecorator.new(@event, @instances)
|
33
|
+
|
34
|
+
yield if block_given?
|
35
|
+
end
|
36
|
+
|
37
|
+
def book_instance
|
38
|
+
@event = Rooftop::Events::Event.where(slug: params[:event_id]).first
|
39
|
+
@instance_id = params[:instance_id]
|
40
|
+
|
41
|
+
yield if block_given?
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module BookingInformation
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def date_from
|
8
|
+
if event_instance_dates[:first].present?
|
9
|
+
DateTime.parse(event_instance_dates[:first])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def date_to
|
14
|
+
if event_instance_dates[:last].present?
|
15
|
+
DateTime.parse(event_instance_dates[:last])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Cache
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
if ::Rails.configuration.action_controller.perform_caching
|
8
|
+
base.send(:alias_method_chain, :related_events, :caching)
|
9
|
+
end
|
10
|
+
|
11
|
+
base.class_eval do
|
12
|
+
class << self
|
13
|
+
alias_method_chain :expire_cache_for, :related
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def related_cache_key
|
20
|
+
"#{self.class.related_cache_key_base}/#{id}"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def related_events_with_caching(opts = {})
|
25
|
+
Rails.cache.fetch(related_cache_key) do
|
26
|
+
related_events_without_caching(opts)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def related_cache_key_base
|
32
|
+
"#{cache_key_base}/related"
|
33
|
+
end
|
34
|
+
|
35
|
+
def expire_cache_for_with_related(*args)
|
36
|
+
::Rails.cache.delete_matched("#{related_cache_key_base}*")
|
37
|
+
expire_cache_for_without_related(args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module InstanceCache
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
|
8
|
+
base.class_eval do
|
9
|
+
class << self
|
10
|
+
alias_method_chain :expire_cache_for, :parent
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def parent_event_id_cache_key
|
17
|
+
"#{self.class.parent_event_id_cache_key_base}/#{id}"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Cache the parent ID into a key
|
21
|
+
def cache_parent_id
|
22
|
+
if self.respond_to?(:event_id)
|
23
|
+
Rails.cache.write(parent_event_id_cache_key, self.event_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
|
29
|
+
def parent_event_id_cache_key_base
|
30
|
+
"#{cache_key_base}/parent_event"
|
31
|
+
end
|
32
|
+
|
33
|
+
def expire_cache_for_with_parent(*args)
|
34
|
+
ids = args.collect {|a| a.respond_to?(:id) ? a.id : a}.flatten.collect(&:to_i)
|
35
|
+
|
36
|
+
#Parent events IDs are stored in a series of keys, one for each instance id. We get all the event ID keys into an array
|
37
|
+
parent_event_id_cache_keys = get_parent_id_cache_keys(ids)
|
38
|
+
# then we get read_multi to get them all from the cache, and derive a unique set of event ids
|
39
|
+
|
40
|
+
event_ids = get_event_ids_from_cache(parent_event_id_cache_keys)
|
41
|
+
if event_ids.count != ids.count #we have some missing event IDs, so we need to do an expensive lookup
|
42
|
+
Rooftop::Events::Event.all(
|
43
|
+
include_embedded_resources: true,
|
44
|
+
instances_per_page: -1,
|
45
|
+
no_filter: [
|
46
|
+
:include_embedded_resources,
|
47
|
+
:instance_per_page
|
48
|
+
]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Now we've hopefully cached them all, do the cache lookup again
|
53
|
+
|
54
|
+
get_event_ids_from_cache(parent_event_id_cache_keys).each do |event_id|
|
55
|
+
Rooftop::Events::Event.expire_cache_for(event_id.to_i)
|
56
|
+
end
|
57
|
+
|
58
|
+
#then we do the normal cache expiry
|
59
|
+
expire_cache_for_without_parent(*args)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def get_parent_id_cache_keys(ids)
|
64
|
+
ids.collect {|id| "#{parent_event_id_cache_key_base}/#{id}"}
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_event_ids_from_cache(keys)
|
68
|
+
Rails.cache.read_multi(*keys).collect {|key, event_id| event_id}.uniq
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Scopes
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
|
9
|
+
scope :after_date, ->(date) {
|
10
|
+
where(
|
11
|
+
meta_key: :last_event_instance,
|
12
|
+
meta_query: {
|
13
|
+
key: :last_event_instance,
|
14
|
+
value: date,
|
15
|
+
compare: '>='
|
16
|
+
},
|
17
|
+
orderby: :meta_value_num,
|
18
|
+
order: :asc
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
scope :in_future, -> {
|
23
|
+
after_date(Date.today)
|
24
|
+
}
|
25
|
+
|
26
|
+
scope :showing_between, ->(from,to) {
|
27
|
+
to_a.select { |e|
|
28
|
+
from.beginning_of_day <= DateTime.parse(e.event_instance_dates[:last]) && to.end_of_day >= DateTime.parse(e.event_instance_dates[:first])
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
scope :showing_on, ->(date) {
|
33
|
+
showing_between(date,date)
|
34
|
+
}
|
35
|
+
|
36
|
+
scope :showing_from, ->(date) {
|
37
|
+
to_a.select {|e| date.beginning_of_day >= DateTime.parse(e.event_instance_dates[:first])}
|
38
|
+
}
|
39
|
+
|
40
|
+
scope :matching_query, ->(q) {
|
41
|
+
search(q)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rooftop/rails/events"
|
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
|
data/bin/setup
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'require_all'
|
2
|
+
require 'rooftop'
|
3
|
+
require 'rooftop/rails'
|
4
|
+
|
5
|
+
require "rooftop/rails/events/version"
|
6
|
+
require "rooftop/rails/events/engine"
|
7
|
+
require "rooftop/rails/events/decorators"
|
8
|
+
require "rooftop/rails/events/instance_decorators"
|
9
|
+
module Rooftop
|
10
|
+
module Rails
|
11
|
+
module Events
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_rel 'decorators'
|
2
|
+
module Rooftop
|
3
|
+
module Rails
|
4
|
+
module Events
|
5
|
+
module Decorators
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
raise StandardError, "Rooftop::Rails::Events::Decorators expects to be mixed into a Draper decorator" unless defined?(Draper) && base.ancestors.include?(Draper::Decorator)
|
9
|
+
base.send(:include, Rooftop::Rails::Events::Content)
|
10
|
+
base.send(:include, Rooftop::Rails::Events::Cast)
|
11
|
+
base.send(:include, Rooftop::Rails::Events::Media)
|
12
|
+
base.send(:include, Rooftop::Rails::Events::Reviews)
|
13
|
+
base.send(:include, Rooftop::Rails::Events::Times)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Cast
|
5
|
+
|
6
|
+
def cast_members
|
7
|
+
if object.has_field?(:cast, Array)
|
8
|
+
object.fields.cast.collect{|cm| PersonDecorator.new(cm)}
|
9
|
+
else
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def creatives
|
15
|
+
if object.has_field?(:creatives, Array)
|
16
|
+
object.fields.creatives.collect{|cm| PersonDecorator.new(cm)}
|
17
|
+
else
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Content
|
5
|
+
|
6
|
+
def title
|
7
|
+
object.title.html_safe
|
8
|
+
end
|
9
|
+
|
10
|
+
def content
|
11
|
+
h.parse_content object.fields.content
|
12
|
+
end
|
13
|
+
|
14
|
+
def excerpt
|
15
|
+
h.parse_content object.fields.excerpt
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
class EventDetailDecorator
|
5
|
+
attr_reader :grouped, :price_lists, :date_ranges, :month_ranges, :accessibility, :instances, :month_ranges_with_sorted_instances
|
6
|
+
|
7
|
+
def initialize(event, instances)
|
8
|
+
@instances = instances ? instances : Rooftop::Events::Instance.all(event_id: event.id,include_embedded_resources: true)
|
9
|
+
|
10
|
+
price_list_ids = @instances.collect{|i| i.price_list_id.to_i}.sort.uniq
|
11
|
+
@price_lists = Rooftop::Events::PriceList.where(post__in: price_list_ids,include_embedded_resources: true).to_a
|
12
|
+
|
13
|
+
@date_ranges = grouped_by_performance_type!
|
14
|
+
|
15
|
+
@accessibility = grouped_by_access_feature!
|
16
|
+
|
17
|
+
@month_ranges = grouped_by_month!
|
18
|
+
|
19
|
+
@month_ranges_with_sorted_instances = grouped_by_month_with_sorted_instances
|
20
|
+
end
|
21
|
+
|
22
|
+
# group events by their performance types.
|
23
|
+
# type being, perview, evening, matinee, or other (special)
|
24
|
+
def grouped_by_performance_type!
|
25
|
+
performance_types = {'preview' => [], 'special_performance' => []}
|
26
|
+
|
27
|
+
@instances.each do |instance|
|
28
|
+
performance_type = instance.meta_attributes["time_of_day"]
|
29
|
+
performance_types[performance_type] ||= []
|
30
|
+
|
31
|
+
if instance.meta_attributes["preview"]=="true"
|
32
|
+
performance_types["preview"].push(instance)
|
33
|
+
end
|
34
|
+
|
35
|
+
if instance.meta_attributes.has_key?("time_of_day")
|
36
|
+
time_of_day = instance.meta_attributes["time_of_day"]
|
37
|
+
performance_types[time_of_day] ||= []
|
38
|
+
|
39
|
+
performance_types[time_of_day].push(instance)
|
40
|
+
else
|
41
|
+
performance_types['special_performance'].push(instance)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
performance_types.each do |type, instances|
|
46
|
+
performance_types[type] = slice_instances_by_date(instances.reverse)
|
47
|
+
end
|
48
|
+
|
49
|
+
Hash[performance_types.reject{|k,v| k.nil? || k.empty? || v.empty?}.sort]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Group the event instances by any known available accessibility facilities
|
53
|
+
#
|
54
|
+
def grouped_by_access_feature!
|
55
|
+
groups = {'audio_described_performance' => [], 'captioned_performance' => [], 'signed_performance' => [], 'touch_tour' => [], 'relaxed_performance' => [], 'talk_back' => []}
|
56
|
+
|
57
|
+
@instances.each do |instance|
|
58
|
+
instance_types = instance.meta_attributes.select{|attr_key, attr_value| groups.keys.include?(attr_key) && attr_value=="true"}.keys
|
59
|
+
|
60
|
+
if instance_types.any?
|
61
|
+
instance_types.each do |type|
|
62
|
+
groups[type].push(instance)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
groups.each do |type, instances|
|
68
|
+
groups[type] = slice_instances_by_date(instances.reverse)
|
69
|
+
end
|
70
|
+
|
71
|
+
groups
|
72
|
+
end
|
73
|
+
|
74
|
+
def grouped_by_month!
|
75
|
+
sorted_instances = @instances.sort_by{|instance| DateTime.parse(instance.meta_attributes[:availability][:starts_at]).at_midnight}
|
76
|
+
|
77
|
+
sorted_instances.group_by do |instance|
|
78
|
+
DateTime.parse(instance.meta_attributes[:availability][:starts_at]).strftime('%B %Y')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def grouped_by_month_with_sorted_instances
|
83
|
+
sorted_instances = @instances.sort_by{|instance| DateTime.parse(instance.meta_attributes[:availability][:starts_at])}
|
84
|
+
sorted_instances.group_by do |instance| DateTime.parse(instance.meta_attributes[:availability][:starts_at]).strftime('%B %Y') end
|
85
|
+
end
|
86
|
+
|
87
|
+
def today
|
88
|
+
for_date(Date.today)
|
89
|
+
end
|
90
|
+
|
91
|
+
def tomorrow
|
92
|
+
for_date(Date.tomorrow)
|
93
|
+
end
|
94
|
+
|
95
|
+
def for_date(date)
|
96
|
+
@instances.sort_by{|instance| DateTime.parse(instance.meta_attributes[:availability][:starts_at])}.select {|instance| DateTime.parse(instance.meta_attributes[:availability][:starts_at]).to_date == date}
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
# sort the given instances and return a grouped result-set, splitting on sets of event instances that have > 1 day between them.
|
104
|
+
# for example, given an array of instances with the dates:
|
105
|
+
#
|
106
|
+
# [1st, 2nd, 3rd, 8th, 9th, 15th]
|
107
|
+
#
|
108
|
+
# we should return a grouped array:
|
109
|
+
#
|
110
|
+
# [[1st, 2nd, 3rd], [8th], [9th], [15th]]
|
111
|
+
#
|
112
|
+
# We can then iterate over these arrays and present the data (1st - 3rd, 8th, 9th and 15th)
|
113
|
+
#
|
114
|
+
def slice_instances_by_date(instances)
|
115
|
+
instance_dates = instances.collect{|i| instance_date(i)}.sort.uniq
|
116
|
+
instance_dates = instance_dates.slice_when{|prev, curr| prev != curr-1.day}.to_a
|
117
|
+
|
118
|
+
group = {}
|
119
|
+
|
120
|
+
instance_dates.each_with_index do |date_range, i|
|
121
|
+
date_range.each do |date|
|
122
|
+
group[i] ||= []
|
123
|
+
group[i].push(instances.select{|i| instance_date(i)==date})
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
group.inject({}) do |h,(k,v)|
|
128
|
+
h[k] = v.flatten unless v.empty?
|
129
|
+
h
|
130
|
+
end.values.reject(&:empty?)
|
131
|
+
end
|
132
|
+
|
133
|
+
# return the event instance (ignores the time)
|
134
|
+
#
|
135
|
+
def instance_date(instance)
|
136
|
+
Time.parse(instance.meta_attributes[:availability][:starts_at]).at_midnight
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module InstanceDecorator
|
5
|
+
|
6
|
+
def start_date_object
|
7
|
+
DateTime.parse(object.meta_attributes[:availability][:starts_at])
|
8
|
+
end
|
9
|
+
|
10
|
+
def start_date
|
11
|
+
start_date_object.strftime("%a %-d %-b")
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_time
|
15
|
+
start_date_object.strftime("%l:%M%P")
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def price(event_details)
|
20
|
+
price_list = event_details.price_lists.find{|pl| pl.id == object.price_list_id.to_i}
|
21
|
+
|
22
|
+
if price_list
|
23
|
+
price_list_range(price_list)
|
24
|
+
else
|
25
|
+
""
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def limited_availability?
|
30
|
+
available = event_instance_meta[:availability][:seats_available].to_i
|
31
|
+
capacity = event_instance_meta[:availability][:seats_capacity].to_i
|
32
|
+
|
33
|
+
available <= capacity/10
|
34
|
+
end
|
35
|
+
|
36
|
+
def in_future?
|
37
|
+
DateTime.parse(object.event_instance_meta[:availability][:starts_at]).future?
|
38
|
+
end
|
39
|
+
|
40
|
+
def in_past?
|
41
|
+
!in_future?
|
42
|
+
end
|
43
|
+
|
44
|
+
def bookable?
|
45
|
+
return false if in_past?
|
46
|
+
|
47
|
+
available = event_instance_meta[:availability][:seats_available].to_i
|
48
|
+
available > 0
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_public_dress_rehearsal?
|
52
|
+
event_instance_meta.has_key?(:public_dress_rehearsal) && event_instance_meta[:public_dress_rehearsal]=="true"
|
53
|
+
end
|
54
|
+
|
55
|
+
def price_list_range(price_list)
|
56
|
+
prices = price_list.prices.collect{|p| p.event_price_meta[:ticket_price].to_f}.flatten.sort
|
57
|
+
[prices[0], prices[-1]].uniq.sort
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Media
|
5
|
+
|
6
|
+
# Images. Requires ACF setup.
|
7
|
+
|
8
|
+
def has_hero_image?
|
9
|
+
has_field?(:hero_image) && fields.hero_image.present?
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_poster_image?
|
13
|
+
has_field(:poster_image) && fields.poster_image.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_list_image?
|
17
|
+
has_field?(:event_list_image) && fields.event_list_image.present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def hero_image
|
21
|
+
has_hero_image? ? fields.hero_image[:sizes][:large] : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def header_image
|
25
|
+
if has_hero_image?
|
26
|
+
hero_image
|
27
|
+
else
|
28
|
+
'https://placeholdit.imgix.net/~text?txtsize=33&txt=350×150&w=1200&h=670'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def list_image
|
33
|
+
if has_list_image?
|
34
|
+
fields.event_list_image[:sizes][:medium]
|
35
|
+
elsif has_hero_image?
|
36
|
+
hero_image
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def poster_image
|
41
|
+
if has_poster_image?
|
42
|
+
fields.poster_image[:sizes][:medium]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Media. Requires ACF.
|
47
|
+
|
48
|
+
def media
|
49
|
+
if object.has_field?(:media, Array) && object.fields.media.any?
|
50
|
+
object.fields.media.collect do |media_item|
|
51
|
+
collection = Rooftop::Content::Collection.new(media_item.collect(&:to_h))
|
52
|
+
|
53
|
+
next unless collection.video_or_image.present?
|
54
|
+
|
55
|
+
if collection.video_or_image == "video" && collection.youtube_url.present?
|
56
|
+
collection << Rooftop::Content::Field.new({name: "youtube_id", value: collection.youtube_url.match(/(youtu.be\/(\S+)$|v=(\S+))/).to_a.compact.last})
|
57
|
+
end
|
58
|
+
collection
|
59
|
+
end
|
60
|
+
else
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def media_collection
|
66
|
+
media.collect do |item|
|
67
|
+
if item.video_or_image == 'image'
|
68
|
+
next unless item.image.is_a?(Hash)
|
69
|
+
{
|
70
|
+
title: item.caption.html_safe,
|
71
|
+
thumbnail: item.image[:sizes][:medium],
|
72
|
+
href: item.image[:sizes][:large],
|
73
|
+
media_type: item.video_or_image,
|
74
|
+
}
|
75
|
+
elsif item.video_or_image == "video"
|
76
|
+
{
|
77
|
+
title: item.caption.html_safe,
|
78
|
+
href: item.youtube_url,
|
79
|
+
type: 'text/html',
|
80
|
+
youtube: item.youtube_id,
|
81
|
+
thumbnail: '//img.youtube.com/vi/' + item.youtube_id + '/0.jpg',
|
82
|
+
poster: '//img.youtube.com/vi/' + item.youtube_id + '/0.jpg',
|
83
|
+
media_type: item.video_or_image,
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def media_json
|
90
|
+
media_collection.compact.to_json.html_safe
|
91
|
+
end
|
92
|
+
|
93
|
+
def has_trailer?
|
94
|
+
has_field?(:trailer) && fields.trailer.present?
|
95
|
+
end
|
96
|
+
|
97
|
+
def trailer
|
98
|
+
if has_trailer?
|
99
|
+
"https://www.youtube.com/embed/" + fields.trailer.partition('=').last + "?rel=0&showinfo=0"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def media_images
|
104
|
+
media.select {|m| m.video_or_image == 'image'}
|
105
|
+
end
|
106
|
+
|
107
|
+
def media_videos
|
108
|
+
media.select {|m| m.video_or_image == 'video'}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
class PersonDecorator
|
5
|
+
attr_reader :attributes, :object, :advanced_fields
|
6
|
+
|
7
|
+
def initialize(relationship)
|
8
|
+
@attributes = {}
|
9
|
+
@object = relationship
|
10
|
+
|
11
|
+
@object.each do |key, value|
|
12
|
+
@attributes[key] = value
|
13
|
+
self.class.send(:attr_accessor, "#{key}")
|
14
|
+
instance_variable_set "@#{key}", value
|
15
|
+
end
|
16
|
+
|
17
|
+
if relationship.has_key?(:advanced) && relationship[:advanced].first && relationship[:advanced].first
|
18
|
+
@advanced_fields = Rooftop::Content::Collection.new(relationship[:advanced].collect{|adv| adv[:fields].first})
|
19
|
+
|
20
|
+
relationship[:advanced].collect{|adv| adv[:fields]}.flatten.each do |field|
|
21
|
+
self.class.send(:attr_accessor, "#{field[:name]}_field")
|
22
|
+
instance_variable_set("@#{field[:name]}_field", field[:value])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def role
|
28
|
+
self.respond_to?(:role_field) ? self.role_field : ''
|
29
|
+
end
|
30
|
+
|
31
|
+
def character
|
32
|
+
self.respond_to?(:character_played_field) ? self.character_played_field : ''
|
33
|
+
end
|
34
|
+
|
35
|
+
def image
|
36
|
+
(self.respond_to?(:headshot_field) && self.headshot_field.is_a?(Hash)) ? self.headshot_field[:sizes][:medium] : ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def content
|
40
|
+
h.parse_content(self.fields.content).html_safe
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Reviews
|
5
|
+
|
6
|
+
# Reviews. Requires ACF setup.
|
7
|
+
|
8
|
+
def has_featured_review?
|
9
|
+
has_field?(:featured_review) && fields.featured_review.present?
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_reviews?
|
13
|
+
has_field?(:reviews) && fields.reviews.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
def featured_review
|
17
|
+
has_featured_review? ? Rooftop::Content::Collection.new(fields.featured_review.first[:advanced].first[:fields]) : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def reviews
|
21
|
+
if has_reviews?
|
22
|
+
fields.reviews.collect do |review|
|
23
|
+
Rooftop::Content::Collection.new(review[:advanced].first[:fields])
|
24
|
+
end
|
25
|
+
else
|
26
|
+
return []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
module Times
|
5
|
+
|
6
|
+
def has_instance_availabilities?
|
7
|
+
respond_to?(:event_instance_availabilities) && event_instance_availabilities.size>0
|
8
|
+
end
|
9
|
+
|
10
|
+
def date_range
|
11
|
+
dates = event_instance_availabilities.first.values.collect{|instance| DateTime.parse(instance[:starts_at])}.sort
|
12
|
+
range = [dates[0], dates[-1]].uniq
|
13
|
+
end
|
14
|
+
|
15
|
+
def has_running_time?
|
16
|
+
meta_attributes[:duration].present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def running_time
|
20
|
+
if has_running_time?
|
21
|
+
t = meta_attributes[:duration].to_i
|
22
|
+
mm, ss = t.divmod(60) #=> [4515, 21]
|
23
|
+
hh, mm = mm.divmod(60) #=> [75, 15]
|
24
|
+
dd, hh = hh.divmod(24) #=> [3, 3]
|
25
|
+
time = ""
|
26
|
+
if mm == 0
|
27
|
+
time = "About #{h.pluralize(hh,'hour')}"
|
28
|
+
elsif hh == 0
|
29
|
+
time = "About #{h.pluralize(mm,'minute')}"
|
30
|
+
else
|
31
|
+
time = "About #{h.pluralize(hh, 'hour')} and #{h.pluralize(mm,'minute')}"
|
32
|
+
end
|
33
|
+
time
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
module Events
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
|
6
|
+
isolate_namespace Rooftop::Rails::Events
|
7
|
+
|
8
|
+
config.before_initialize do
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer "add_helpers" do
|
13
|
+
ActiveSupport.on_load(:action_view) do
|
14
|
+
# include Rooftop::Rails::Events::YourHelper
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
config.to_prepare do
|
20
|
+
::Rails.application.eager_load!
|
21
|
+
Rooftop::Events::Event.send(:include, Rooftop::Rails::Events::Cache)
|
22
|
+
Rooftop::Events::Event.send(:include, Rooftop::Rails::Events::Scopes)
|
23
|
+
# Rooftop::Events::Instance.send(:include, Rooftop::Rails::Events::InstanceCache)
|
24
|
+
Rooftop::Events::Instance.send(:include, Rooftop::Rails::Events::BookingInformation)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_rel "./decorators"
|
2
|
+
module Rooftop
|
3
|
+
module Rails
|
4
|
+
module Events
|
5
|
+
module InstanceDecorators
|
6
|
+
def self.included(base)
|
7
|
+
raise StandardError, "Rooftop::Rails::Events::InstanceDecorators expects to be mixed into a Draper decorator" unless defined?(Draper) && base.ancestors.include?(Draper::Decorator)
|
8
|
+
base.send(:include, Rooftop::Rails::Events::InstanceDecorator)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rooftop/rails/events/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rooftop-rails-events"
|
8
|
+
spec.version = Rooftop::Rails::Events::VERSION
|
9
|
+
spec.authors = ["Ed Jones"]
|
10
|
+
spec.email = ["ed@errorstudio.co.uk"]
|
11
|
+
|
12
|
+
spec.summary = %q{Quickly add events to your Rails website with Rooftop CMS.}
|
13
|
+
spec.description = %q{This library integrates with Rooftop CMS's events plugin to make it easy to add events to your site.}
|
14
|
+
spec.homepage = "https://github.com/rooftopcms/rooftop-rails-events"
|
15
|
+
spec.license = "GPLv3"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
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_development_dependency "bundler", "~> 1.11"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
|
25
|
+
spec.add_dependency "require_all"
|
26
|
+
spec.add_dependency "rooftop-rails"
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rooftop-rails-events
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ed Jones
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: require_all
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rooftop-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: This library integrates with Rooftop CMS's events plugin to make it easy
|
70
|
+
to add events to your site.
|
71
|
+
email:
|
72
|
+
- ed@errorstudio.co.uk
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- app/controllers/concerns/rooftop/rails/events/event_collections.rb
|
83
|
+
- app/controllers/concerns/rooftop/rails/events/event_handler.rb
|
84
|
+
- app/controllers/concerns/rooftop/rails/events/event_search.rb
|
85
|
+
- app/models/concerns/rooftop/rails/events/booking_information.rb
|
86
|
+
- app/models/concerns/rooftop/rails/events/cache.rb
|
87
|
+
- app/models/concerns/rooftop/rails/events/instance_cache.rb
|
88
|
+
- app/models/concerns/rooftop/rails/events/scopes.rb
|
89
|
+
- bin/console
|
90
|
+
- bin/setup
|
91
|
+
- lib/rooftop/rails/events.rb
|
92
|
+
- lib/rooftop/rails/events/decorators.rb
|
93
|
+
- lib/rooftop/rails/events/decorators/cast.rb
|
94
|
+
- lib/rooftop/rails/events/decorators/content.rb
|
95
|
+
- lib/rooftop/rails/events/decorators/event_detail_decorator.rb
|
96
|
+
- lib/rooftop/rails/events/decorators/instance_decorator.rb
|
97
|
+
- lib/rooftop/rails/events/decorators/media.rb
|
98
|
+
- lib/rooftop/rails/events/decorators/person_decorator.rb
|
99
|
+
- lib/rooftop/rails/events/decorators/reviews.rb
|
100
|
+
- lib/rooftop/rails/events/decorators/times.rb
|
101
|
+
- lib/rooftop/rails/events/engine.rb
|
102
|
+
- lib/rooftop/rails/events/instance_decorators.rb
|
103
|
+
- lib/rooftop/rails/events/version.rb
|
104
|
+
- rooftop-rails-events.gemspec
|
105
|
+
homepage: https://github.com/rooftopcms/rooftop-rails-events
|
106
|
+
licenses:
|
107
|
+
- GPLv3
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.2.2
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Quickly add events to your Rails website with Rooftop CMS.
|
129
|
+
test_files: []
|