effective_events 0.1.10 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '069d27a813f8daeb16748df4948a0e653dbe0bb8d3a853e5fe8ef24fda74729c'
4
- data.tar.gz: 2214b6dbdac9cc9e824948303ff983a4aef264fc4544bb43dca0d208a492612c
3
+ metadata.gz: cd744d00aed47ee8fe88bbfa4f9224f6dea924726a9d7f42be397e88315e5a0f
4
+ data.tar.gz: b24c00d8bc3a54e3ccad2f43db728ede8a53b5aaff618646386c3ad179c827ed
5
5
  SHA512:
6
- metadata.gz: 37f1f2d5c00228a0bfbc67ca1aeb49eb70b0691945c06bea4a2432d307658059bbc14bae09d7089c9bea649ab45ecd849bb44af087a90792f3d30827c45411bc
7
- data.tar.gz: 41f9da86b0be58b72eff25b4fd1853105e63be29782787135d90abd8e38fcec7910da9846e640f845635a7424039c3d852e0ebe4fb0032fbaadbd369bc1c4931
6
+ metadata.gz: bee221260b8e2aad273c9b79250707bf4c053dc64a937c3eff477eb345e8bc3a10afb4b9504d45f2d2be778a842a62ffc7dc4a9ac76138915575eff8c295524c
7
+ data.tar.gz: 305c28be0450a00d070e15d32d0af3dc2de4c72bdbad1e345948c00851ccb882566b84b9a256d9c62786573902cced56a63a658204fd671614d4e59ebc3a58f2
@@ -0,0 +1,8 @@
1
+ module Admin
2
+ class EventNotificationsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_events) }
5
+
6
+ include Effective::CrudController
7
+ end
8
+ end
@@ -39,7 +39,6 @@ module Effective
39
39
 
40
40
  def permitted_params
41
41
  model = (params.key?(:effective_event_registration) ? :effective_event_registration : :event_registration)
42
-
43
42
  params.require(model).permit!.except(:status, :status_steps, :wizard_steps, :submitted_at)
44
43
  end
45
44
 
@@ -8,7 +8,7 @@ module Effective
8
8
  }
9
9
 
10
10
  def index
11
- @events ||= resource_scope
11
+ @events ||= resource_scope.published
12
12
 
13
13
  @events = @events.paginate(page: params[:page])
14
14
 
@@ -0,0 +1,52 @@
1
+ class Admin::EffectiveEventNotificationsDatatable < Effective::Datatable
2
+ # filters do
3
+ # scope :all
4
+ # scope :started
5
+ # scope :completed
6
+ # end
7
+
8
+ datatable do
9
+ col :updated_at, visible: false
10
+ col :created_at, visible: false
11
+ col :id, visible: false
12
+
13
+ col :event
14
+ col :category
15
+
16
+ col :from do |event|
17
+ html_escape(event.from)
18
+ end
19
+
20
+ # col :reminder do |poll_notification|
21
+ # case poll_notification.category
22
+ # when 'When poll starts'
23
+ # poll_notification.poll.start_at&.strftime('%F %H:%M')
24
+ # when 'When poll ends'
25
+ # poll_notification.poll.end_at&.strftime('%F %H:%M')
26
+ # when 'Upcoming reminder'
27
+ # Effective::PollNotification::UPCOMING_REMINDERS.invert[poll_notification.reminder]
28
+ # when 'Reminder'
29
+ # Effective::PollNotification::REMINDERS.invert[poll_notification.reminder]
30
+ # when 'Before poll ends'
31
+ # Effective::PollNotification::UPCOMING_REMINDERS.invert[poll_notification.reminder]
32
+ # else
33
+ # raise('unexpected category')
34
+ # end
35
+ # end
36
+
37
+ col :subject
38
+
39
+ col :body do |notification|
40
+ simple_format(notification.body)
41
+ end
42
+
43
+ # col :started_at, visible: false
44
+ # col :completed_at
45
+
46
+ actions_col
47
+ end
48
+
49
+ collection do
50
+ Effective::EventNotification.all.deep
51
+ end
52
+ end
@@ -14,6 +14,8 @@ module Admin
14
14
  col :id, visible: false
15
15
 
16
16
  col :title
17
+ col :slug, visible: false
18
+
17
19
  col :draft
18
20
  col :start_at, label: 'Event Start Date'
19
21
  col :end_at, label: 'Event End Date', visible: false
@@ -0,0 +1,56 @@
1
+ module Effective
2
+ class EventsMailer < EffectiveResources.parent_mailer_class
3
+ default from: -> { EffectiveResources.mailer_sender }
4
+ layout -> { EffectiveResources.mailer_layout }
5
+
6
+ include EffectiveEmailTemplatesMailer if EffectiveEvents.use_effective_email_templates
7
+
8
+ def event_registrant_purchased(event_registrant, opts = {})
9
+ @assigns = assigns_for(event_registrant)
10
+ @event_registrant = event_registrant
11
+
12
+ mail(to: event_registrant.email, **headers_for(event_registrant, opts))
13
+ end
14
+
15
+ protected
16
+
17
+ def headers_for(resource, opts = {})
18
+ resource.respond_to?(:log_changes_datatable) ? opts.merge(log: resource) : opts
19
+ end
20
+
21
+ def assigns_for(resource)
22
+ if resource.kind_of?(EventRegistrant)
23
+ return event_registrant_assigns(resource).merge(event_assigns(resource.event)).merge(event_ticket_assigns(resource.event_ticket))
24
+ end
25
+
26
+ raise('unexpected resource')
27
+ end
28
+
29
+ def event_assigns(resource)
30
+ raise('expected an event') unless resource.kind_of?(Event)
31
+
32
+ values = {
33
+ name: resource.title,
34
+ date: resource.start_at.strftime('%F %H:%M'),
35
+ url: effective_events.event_url(resource)
36
+ }
37
+
38
+ { event: values }
39
+ end
40
+
41
+ def event_ticket_assigns(resource)
42
+ raise('expected an event ticket') unless resource.kind_of?(EventTicket)
43
+
44
+ values = { name: resource.title }
45
+ { ticket: values }
46
+ end
47
+
48
+ def event_registrant_assigns(resource)
49
+ raise('expected an event registrant') unless resource.kind_of?(EventRegistrant)
50
+
51
+ values = { name: resource.name, email: resource.email }
52
+ { registrant: values }
53
+ end
54
+
55
+ end
56
+ end
@@ -118,6 +118,11 @@ module EffectiveEventsEventRegistration
118
118
  (event_registrants + event_addons)
119
119
  end
120
120
 
121
+ def after_submit_purchased!
122
+ notifications = event.event_notifications.select(&:registrant_purchased?)
123
+ notifications.each { |notification| notification.notify!(event_registrants: event_registrants) }
124
+ end
125
+
121
126
  end
122
127
 
123
128
  # Instance Methods
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Effective
4
4
  class Event < ActiveRecord::Base
5
- has_many :event_tickets, -> { EventTicket.sorted }, inverse_of: :event
5
+ has_many :event_tickets, -> { EventTicket.sorted }, inverse_of: :event, dependent: :destroy
6
6
  accepts_nested_attributes_for :event_tickets, allow_destroy: true
7
7
 
8
- has_many :event_products, -> { EventProduct.sorted }, inverse_of: :event
8
+ has_many :event_products, -> { EventProduct.sorted }, inverse_of: :event, dependent: :destroy
9
9
  accepts_nested_attributes_for :event_products, allow_destroy: true
10
10
 
11
11
  has_many :event_registrants, -> { order(:event_ticket_id, :created_at) }, inverse_of: :event
@@ -14,6 +14,9 @@ module Effective
14
14
  has_many :event_addons, -> { order(:event_product_id, :created_at) }, inverse_of: :event
15
15
  accepts_nested_attributes_for :event_addons, allow_destroy: true
16
16
 
17
+ has_many :event_notifications, -> { order(:id) }, inverse_of: :event, dependent: :destroy
18
+ accepts_nested_attributes_for :event_notifications, allow_destroy: true
19
+
17
20
  # rich_text_body - Used by the select step
18
21
  has_many_rich_texts
19
22
 
@@ -0,0 +1,160 @@
1
+ module Effective
2
+ class EventNotification < ActiveRecord::Base
3
+ log_changes(to: :event) if respond_to?(:log_changes)
4
+
5
+ belongs_to :event
6
+
7
+ CATEGORIES = ['Registrant purchased']
8
+ EMAIL_TEMPLATE_VARIABLES = ['event.name', 'event.date', 'event.url', 'ticket.name', 'registrant.name', 'registrant.email']
9
+
10
+ #CATEGORIES = ['Upcoming reminder', 'When event starts', 'Reminder', 'Before event ends', 'When event ends']
11
+
12
+ # UPCOMING_REMINDERS = {
13
+ # '1 hour before' => 1.hours.to_i,
14
+ # '3 hours before' => 3.hours.to_i,
15
+ # '6 hours before' => 6.hours.to_i,
16
+ # '12 hours before' => 12.hours.to_i,
17
+ # '1 day before' => 1.days.to_i,
18
+ # '2 days before' => 2.days.to_i,
19
+ # '3 days before' => 3.days.to_i,
20
+ # '4 days before' => 4.days.to_i,
21
+ # '5 days before' => 5.days.to_i,
22
+ # '6 days before' => 6.days.to_i,
23
+ # '1 week before' => 1.weeks.to_i,
24
+ # '2 weeks before' => 2.weeks.to_i,
25
+ # '3 weeks before' => 3.weeks.to_i,
26
+ # '1 month before' => 1.month.to_i
27
+ # }
28
+
29
+ # REMINDERS = {
30
+ # '1 hour after' => 1.hours.to_i,
31
+ # '3 hours after' => 3.hours.to_i,
32
+ # '6 hours after' => 6.hours.to_i,
33
+ # '12 hours after' => 12.hours.to_i,
34
+ # '1 day after' => 1.days.to_i,
35
+ # '2 days after' => 2.days.to_i,
36
+ # '3 days after' => 3.days.to_i,
37
+ # '4 days after' => 4.days.to_i,
38
+ # '5 days after' => 5.days.to_i,
39
+ # '6 days after' => 6.days.to_i,
40
+ # '1 week after' => 1.weeks.to_i,
41
+ # '2 weeks after' => 2.weeks.to_i,
42
+ # '3 weeks after' => 3.weeks.to_i,
43
+ # '1 month after' => 1.month.to_i
44
+ # }
45
+
46
+ effective_resource do
47
+ category :string
48
+ reminder :integer # Number of seconds before event.start_at
49
+
50
+ # Email
51
+ from :string
52
+ subject :string
53
+ body :text
54
+
55
+ # Tracking background jobs email send out
56
+ started_at :datetime
57
+ completed_at :datetime
58
+
59
+ timestamps
60
+ end
61
+
62
+ scope :sorted, -> { order(:id) }
63
+ scope :deep, -> { includes(:event) }
64
+
65
+ scope :started, -> { where.not(started_at: nil) }
66
+ scope :completed, -> { where.not(completed_at: nil) }
67
+
68
+ # Called by a future event_notifier rake task
69
+ scope :notifiable, -> { where(started_at: nil, completed_at: nil) }
70
+
71
+ validates :category, presence: true, inclusion: { in: CATEGORIES }
72
+
73
+ validates :from, presence: true, email: true
74
+ validates :subject, presence: true
75
+ validates :body, presence: true
76
+
77
+ if EffectiveEvents.use_effective_email_templates
78
+ validates :body, liquid: true
79
+ validates :subject, liquid: true
80
+ end
81
+
82
+ # validates :reminder, if: -> { reminder? || upcoming_reminder? || before_event_ends? },
83
+ # presence: true, uniqueness: { scope: [:event_id, :category], message: 'already exists' }
84
+
85
+ def to_s
86
+ 'event notification'
87
+ end
88
+
89
+ def email_template
90
+ 'event_' + category.to_s.parameterize.underscore
91
+ end
92
+
93
+ def registrant_purchased?
94
+ category == 'Registrant purchased'
95
+ end
96
+
97
+ # def upcoming_reminder?
98
+ # category == 'Upcoming reminder'
99
+ # end
100
+
101
+ # def event_start?
102
+ # category == 'When event starts'
103
+ # end
104
+
105
+ # def reminder?
106
+ # category == 'Reminder'
107
+ # end
108
+
109
+ # def before_event_ends?
110
+ # category == 'Before event ends'
111
+ # end
112
+
113
+ # def event_end?
114
+ # category == 'When event ends'
115
+ # end
116
+
117
+ # def notifiable?
118
+ # started_at.blank? && completed_at.blank?
119
+ # end
120
+
121
+ def notify_now?
122
+ true
123
+
124
+ #return false unless notifiable?
125
+
126
+ # case category
127
+ # when 'When event starts'
128
+ # event.available?
129
+ # when 'When event ends'
130
+ # event.ended?
131
+ # when 'Upcoming reminder'
132
+ # !event.started? && event.start_at < (Time.zone.now + reminder)
133
+ # when 'Reminder'
134
+ # !event.ended? && event.start_at < (Time.zone.now - reminder)
135
+ # when 'Before event ends'
136
+ # !event.ended? && event.end_at.present? && event.end_at < (Time.zone.now + reminder)
137
+ # else
138
+ # raise('unexpected category')
139
+ # end
140
+ end
141
+
142
+ def notify!(force: false, event_registrants: nil)
143
+ return false unless (notify_now? || force)
144
+
145
+ # We send one email to each registrant
146
+ event_registrants ||= event.event_registrants.purchased
147
+
148
+ update_column(:started_at, Time.zone.now)
149
+
150
+ opts = { from: from, subject: subject, body: body }
151
+
152
+ event_registrants.each do |event_registrant|
153
+ EffectiveEvents.send_email(email_template, event_registrant, opts)
154
+ end
155
+
156
+ update_column(:completed_at, Time.zone.now)
157
+ end
158
+
159
+ end
160
+ end
@@ -58,6 +58,10 @@ module Effective
58
58
  "#{event_ticket} - #{last_first_name}"
59
59
  end
60
60
 
61
+ def name
62
+ "#{first_name} #{last_name}"
63
+ end
64
+
61
65
  def last_first_name
62
66
  "#{last_name}, #{first_name}"
63
67
  end
@@ -0,0 +1,44 @@
1
+ = effective_form_with(model: [:admin, event_notification], engine: true) do |f|
2
+ - if inline_datatable?
3
+ = f.hidden_field :event_id
4
+ - else
5
+ = f.select :event_id, Effective::Event.sorted.all
6
+
7
+ = f.select :category, Effective::EventNotification::CATEGORIES,
8
+ label: 'Send an email notification'
9
+
10
+ - # Render email templates
11
+ - Effective::EventNotification::CATEGORIES.each do |category|
12
+ - template = 'event_' + category.parameterize.underscore
13
+
14
+ = f.show_if :category, category do
15
+ = render "/admin/event_notifications/form_#{template}", f: f
16
+
17
+ - if f.object.category == category && f.object.persisted?
18
+ = f.text_field :from
19
+ = f.text_field :subject
20
+ = f.text_area :body, rows: 10
21
+
22
+ - elsif EffectiveEvents.use_effective_email_templates == false
23
+ = f.text_field :from, value: EffectiveResources.mailer_sender
24
+ = f.text_field :subject, value: ''
25
+ = f.text_area :body, rows: 10, value: ''
26
+
27
+ - else
28
+ - email_template = Effective::EmailTemplate.where(template_name: template).first!
29
+
30
+ = f.text_field :from, value: email_template.from
31
+ = f.text_field :subject, value: email_template.subject
32
+ = f.text_area :body, rows: 10, value: email_template.body
33
+
34
+ - if EffectiveEvents.use_effective_email_templates
35
+
36
+ %p The available variables are:
37
+
38
+ %ul
39
+ - Effective::EventNotification::EMAIL_TEMPLATE_VARIABLES.each do |variable|
40
+ %li {{ #{variable} }}
41
+
42
+ %small.text-muted Only a developer can add additional variables
43
+
44
+ = effective_submit(f)
@@ -0,0 +1,3 @@
1
+ .alert.alert-warning
2
+ %strong When registrant purchased
3
+ notifications will be sent to each registrant at time of purchase.
@@ -16,6 +16,12 @@
16
16
  - datatable = Admin::EffectiveEventProductsDatatable.new(event_id: event.id)
17
17
  = render_inline_datatable(datatable)
18
18
 
19
+ = tab 'Email' do
20
+ %p Click New to add one or more emails.
21
+
22
+ - datatable = Admin::EffectiveEventNotificationsDatatable.new(event_id: event.id)
23
+ = render_datatable(datatable, inline: true, simple: true)
24
+
19
25
  = tab 'Registrations' do
20
26
  %h2 Registrations
21
27
  - datatable = Admin::EffectiveEventRegistrationsDatatable.new(event_id: event.id)
@@ -17,7 +17,7 @@
17
17
  = link_to('Abandon registration', effective_events.event_event_registration_path(registration.event, registration), 'data-confirm': "Really delete #{registration}?", 'data-method': :delete, class: 'btn btn-danger')
18
18
  to register for another event.
19
19
 
20
- %hr
20
+ %hr
21
21
 
22
22
  %h2 Event Registrations
23
23
 
@@ -1,5 +1,5 @@
1
1
  .effective-event
2
- %table.table.effective-events-table
2
+ %table.table.effective-event-table
3
3
  %tbody
4
4
  %tr
5
5
  %td Starts
@@ -0,0 +1,17 @@
1
+ ---
2
+ subject: 'You have been registered for {{ event.title }}'
3
+ from: 'admin@example.com'
4
+ ---
5
+ Hello {{ registrant.name }},
6
+
7
+ Your ticket {{ ticket.name }} has been purchased.
8
+
9
+ You are registered for {{ event.name }}
10
+
11
+ The event starts on {{ event.date }}
12
+
13
+ {{ event.url }}
14
+
15
+ Thank you.
16
+
17
+ Please contact us for assistance.
@@ -18,4 +18,15 @@ EffectiveEvents.setup do |config|
18
18
 
19
19
  # Events can be restricted by role
20
20
  config.use_effective_roles = true
21
+
22
+ # Mailer Configuration
23
+ #
24
+ # Additional mailer settings for parent_mailer, delivery_method, layout, sender and admin
25
+ # are required fields in config/initializers/effective_resources.rb
26
+
27
+ # Configure the class responsible to send e-mails.
28
+ # config.mailer = 'Effective::EventsMailer'
29
+
30
+ # Use effective email templates for event notifications
31
+ config.use_effective_email_templates = true
21
32
  end
data/config/routes.rb CHANGED
@@ -21,6 +21,7 @@ EffectiveEvents::Engine.routes.draw do
21
21
  resources :event_registrants, except: [:show]
22
22
  resources :event_addons, except: [:show]
23
23
  resources :event_registrations, only: [:index, :show]
24
+ resources :event_notifications, except: [:show]
24
25
  end
25
26
 
26
27
  end
@@ -131,5 +131,22 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
131
131
  add_index <%= @event_registrations_table_name %>, :status
132
132
  add_index <%= @event_registrations_table_name %>, :token
133
133
 
134
+ create_table <%= @event_notifications_table_name %> do |t|
135
+ t.references :event
136
+
137
+ t.string :category
138
+ t.integer :reminder
139
+
140
+ t.string :from
141
+ t.string :subject
142
+ t.text :body
143
+
144
+ t.datetime :started_at
145
+ t.datetime :completed_at
146
+
147
+ t.datetime :updated_at
148
+ t.datetime :created_at
149
+ end
150
+
134
151
  end
135
152
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveEvents
2
- VERSION = '0.1.10'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -9,7 +9,8 @@ module EffectiveEvents
9
9
  :events_table_name, :event_registrants_table_name, :event_tickets_table_name,
10
10
  :event_registrations_table_name, :event_products_table_name, :event_addons_table_name,
11
11
  :layout, :per_page, :use_effective_roles,
12
- :event_registration_class_name
12
+ :event_registration_class_name,
13
+ :mailer, :use_effective_email_templates
13
14
  ]
14
15
  end
15
16
 
@@ -19,4 +20,8 @@ module EffectiveEvents
19
20
  event_registration_class_name&.constantize || Effective::EventRegistration
20
21
  end
21
22
 
23
+ def self.mailer_class
24
+ mailer&.constantize || Effective::EventsMailer
25
+ end
26
+
22
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_events
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-17 00:00:00.000000000 Z
11
+ date: 2022-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: effective_email_templates
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  description: Event registrations, tickets and products
168
182
  email:
169
183
  - info@codeandeffect.com
@@ -180,6 +194,7 @@ files:
180
194
  - app/assets/stylesheets/effective_events.scss
181
195
  - app/assets/stylesheets/effective_events/base.scss
182
196
  - app/controllers/admin/event_addons_controller.rb
197
+ - app/controllers/admin/event_notifications_controller.rb
183
198
  - app/controllers/admin/event_products_controller.rb
184
199
  - app/controllers/admin/event_registrants_controller.rb
185
200
  - app/controllers/admin/event_registrations_controller.rb
@@ -188,6 +203,7 @@ files:
188
203
  - app/controllers/effective/event_registrations_controller.rb
189
204
  - app/controllers/effective/events_controller.rb
190
205
  - app/datatables/admin/effective_event_addons_datatable.rb
206
+ - app/datatables/admin/effective_event_notifications_datatable.rb
191
207
  - app/datatables/admin/effective_event_products_datatable.rb
192
208
  - app/datatables/admin/effective_event_registrants_datatable.rb
193
209
  - app/datatables/admin/effective_event_registrations_datatable.rb
@@ -198,14 +214,18 @@ files:
198
214
  - app/datatables/effective_event_registrations_datatable.rb
199
215
  - app/datatables/effective_events_datatable.rb
200
216
  - app/helpers/effective_events_helper.rb
217
+ - app/mailers/effective/events_mailer.rb
201
218
  - app/models/concerns/effective_events_event_registration.rb
202
219
  - app/models/effective/event.rb
203
220
  - app/models/effective/event_addon.rb
221
+ - app/models/effective/event_notification.rb
204
222
  - app/models/effective/event_product.rb
205
223
  - app/models/effective/event_registrant.rb
206
224
  - app/models/effective/event_registration.rb
207
225
  - app/models/effective/event_ticket.rb
208
226
  - app/views/admin/event_addons/_form.html.haml
227
+ - app/views/admin/event_notifications/_form.html.haml
228
+ - app/views/admin/event_notifications/_form_event_registrant_purchased.html.haml
209
229
  - app/views/admin/event_products/_form.html.haml
210
230
  - app/views/admin/event_registrants/_form.html.haml
211
231
  - app/views/admin/event_tickets/_form.html.haml
@@ -237,6 +257,7 @@ files:
237
257
  - app/views/effective/events/_spacer.html.haml
238
258
  - app/views/effective/events/index.html.haml
239
259
  - app/views/effective/events/show.html.haml
260
+ - app/views/effective/events_mailer/event_registrant_purchased.liquid
240
261
  - config/effective_events.rb
241
262
  - config/routes.rb
242
263
  - db/migrate/01_create_effective_events.rb.erb