rooftop-rails-events 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|