Skip to content

Commit 5c23ba3

Browse files
CRUD for Events and create Event Registrations (#127)
1 parent d8eb570 commit 5c23ba3

26 files changed

+1435
-118
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
class EventRegistrationsController < ApplicationController
2+
3+
def create
4+
@event_registration = EventRegistration.new(event_registration_params)
5+
if @event_registration.save
6+
redirect_to @event_registration.event, notice: 'Successfully registered for the event.'
7+
else
8+
redirect_to @event_registration.event, alert: "Registration failed: #{@event_registration.errors.full_messages.join(', ')}"
9+
end
10+
end
11+
12+
def bulk_create
13+
event_ids = Array(params[:event_ids]).map(&:to_i).uniq
14+
if event_ids.blank?
15+
redirect_to events_path, alert: "Please select at least one event."
16+
return
17+
end
18+
19+
attendee_attrs = {
20+
first_name: current_user.first_name || current_user.email.split('@').first,
21+
last_name: current_user.last_name || 'User',
22+
email: current_user.email
23+
}
24+
25+
created = 0
26+
errors = []
27+
28+
Event.transaction do
29+
event_ids.each do |event_id|
30+
existing_registration = EventRegistration.where(
31+
event_id: event_id,
32+
email: attendee_attrs[:email]
33+
).first
34+
35+
if existing_registration
36+
errors << "Event '#{Event.find(event_id).title}': You are already registered for this event."
37+
next
38+
end
39+
40+
reg = EventRegistration.new(attendee_attrs.merge(event_id: event_id))
41+
unless reg.save
42+
errors << "Event '#{Event.find(event_id).title}': #{reg.errors.full_messages.to_sentence}"
43+
else
44+
created += 1
45+
end
46+
end
47+
48+
raise ActiveRecord::Rollback if errors.any?
49+
end
50+
51+
if errors.any?
52+
redirect_to events_path, alert: errors.join("; ")
53+
else
54+
redirect_to events_path, notice: "Successfully registered for #{created} event#{'s' if created != 1}."
55+
end
56+
end
57+
58+
private
59+
60+
def event_registration_params
61+
params.require(:event_registration).permit(:event_id, :first_name, :last_name, :email)
62+
end
63+
end
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
class EventsController < ApplicationController
2+
before_action :set_event, only: %i[ show edit update destroy ]
3+
before_action :authorize_admin!, only: %i[ new edit update destroy ]
4+
5+
def index
6+
@events = Event.all
7+
end
8+
9+
def show
10+
end
11+
12+
def new
13+
@event = Event.new
14+
end
15+
16+
def edit
17+
end
18+
19+
def create
20+
@event = Event.new(event_params)
21+
22+
respond_to do |format|
23+
if @event.save
24+
format.html { redirect_to @event, notice: "Event was successfully created." }
25+
format.json { render :show, status: :created, location: @event }
26+
else
27+
format.html { render :new, status: :unprocessable_entity }
28+
format.json { render json: @event.errors, status: :unprocessable_entity }
29+
end
30+
end
31+
end
32+
33+
def update
34+
respond_to do |format|
35+
if @event.update(event_params)
36+
format.html { redirect_to @event, notice: "Event was successfully updated." }
37+
format.json { render :show, status: :ok, location: @event }
38+
else
39+
format.html { render :edit, status: :unprocessable_entity }
40+
format.json { render json: @event.errors, status: :unprocessable_entity }
41+
end
42+
end
43+
end
44+
45+
def destroy
46+
@event.destroy
47+
48+
respond_to do |format|
49+
format.html { redirect_to events_path, status: :see_other, notice: "Event was successfully destroyed." }
50+
format.json { head :no_content }
51+
end
52+
end
53+
54+
private
55+
56+
def set_event
57+
@event = Event.find(params[:id])
58+
end
59+
60+
def event_params
61+
params.require(:event).permit(:title, :description, :start_date, :end_date, :registration_close_date, :publicly_visible)
62+
end
63+
64+
def authorize_admin!
65+
redirect_to events_path, alert: "You are not authorized to perform this action." unless current_admin
66+
end
67+
end

app/models/event.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Event < ApplicationRecord
2+
has_many :event_registrations, dependent: :destroy
3+
4+
validates_presence_of :title, :start_date, :end_date
5+
validates_inclusion_of :publicly_visible, in: [true, false]
6+
end

app/models/event_registration.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class EventRegistration < ApplicationRecord
2+
belongs_to :event
3+
4+
validates_presence_of :first_name, :last_name, :email, :event_id
5+
validates_uniqueness_of :email, scope: :event_id, message: 'is already registered for this event', case_sensitive: false
6+
validates_format_of :email, with: URI::MailTo::EMAIL_REGEXP
7+
end

app/views/events/_form.html.erb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<%= form_for(@event) do |f| %>
2+
<%= render 'shared/errors', resource: @event if @event.errors.any? %>
3+
4+
<div class="form-group">
5+
<%= f.label :title, class: 'bold' %>
6+
<%= f.text_field :title, class: 'form-control' %>
7+
8+
<%= f.label :description, class: 'bold' %>
9+
<%= f.text_area :description, class: 'form-control' %>
10+
11+
<%= f.label :start_date, class: 'bold' %>
12+
<%= f.text_field :start_date, type: 'datetime-local', class: 'form-control', value: @event.start_date&.strftime('%Y-%m-%dT%H:%M') %>
13+
14+
<%= f.label :end_date, class: 'bold' %>
15+
<%= f.text_field :end_date, type: 'datetime-local', class: 'form-control', value: @event.end_date&.strftime('%Y-%m-%dT%H:%M') %>
16+
17+
<%= f.label :registration_close_date, class: 'bold' %>
18+
<%= f.text_field :registration_close_date, type: 'datetime-local', class: 'form-control', value: @event.registration_close_date&.strftime('%Y-%m-%dT%H:%M') %>
19+
20+
<div style="display: flex; align-items: center; margin-top: 10px; column-gap: 10px;">
21+
<%= f.label :publicly_visible, class: 'bold' %>
22+
<%= f.check_box :publicly_visible, { class: 'bold mt-0' }, '1', '0' %>
23+
</div>
24+
</div>
25+
26+
<div class="form-actions">
27+
<%= f.button :submit, class: 'btn btn-primary' %>
28+
</div>
29+
<% end %>

app/views/events/edit.html.erb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<h1>Editing Event</h1>
2+
3+
<%= render 'form', event: @event %>
4+
5+
<%= link_to 'Show', @event %> |
6+
<%= link_to 'Back', events_path %>

app/views/events/index.html.erb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<p id="notice"><%= notice %></p>
2+
3+
<h1>Events</h1>
4+
5+
<%= form_with url: bulk_create_event_registrations_path, method: :post, local: true, id: 'bulk-registration-form' do |form| %>
6+
<table>
7+
<thead>
8+
<tr>
9+
<th></th>
10+
<th>Title</th>
11+
<th>Start Date</th>
12+
<th>End Date</th>
13+
<th>Actions</th>
14+
</tr>
15+
</thead>
16+
17+
<tbody>
18+
<% @events.each do |event| %>
19+
<tr>
20+
<td style="padding-right: 10px;">
21+
<%= check_box_tag "event_ids[]", event.id, false, class: "event-checkbox" %>
22+
</td>
23+
<td style="padding-right: 10px;"><%= event.title %></td>
24+
<td style="padding-right: 10px;"><%= event.start_date.strftime("%B %d, %Y") if event.start_date %></td>
25+
<td style="padding-right: 10px;"><%= event.end_date.strftime("%B %d, %Y") if event.end_date %></td>
26+
<td style="padding-right: 10px;">
27+
<%= link_to 'Show', event %> |
28+
<%= link_to 'Edit', edit_event_path(event) %> |
29+
<%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %>
30+
</td>
31+
</tr>
32+
<% end %>
33+
</tbody>
34+
</table>
35+
36+
<br>
37+
38+
<div>
39+
<%= form.submit "Register for Selected Events", class: "btn btn-primary", id: "register-button", disabled: true %>
40+
<%= link_to 'New Event', new_event_path, class: "btn btn-primary" %>
41+
</div>
42+
<% end %>
43+
44+
<script>
45+
document.addEventListener('DOMContentLoaded', function() {
46+
const checkboxes = document.querySelectorAll('.event-checkbox');
47+
const registerButton = document.getElementById('register-button');
48+
49+
function updateRegisterButton() {
50+
const checkedBoxes = document.querySelectorAll('.event-checkbox:checked');
51+
registerButton.disabled = checkedBoxes.length === 0;
52+
}
53+
54+
checkboxes.forEach(checkbox => {
55+
checkbox.addEventListener('change', updateRegisterButton);
56+
});
57+
58+
updateRegisterButton();
59+
});
60+
</script>

app/views/events/new.html.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<h1>New Event</h1>
2+
3+
<%= render 'form', event: @event %>
4+
5+
<%= link_to 'Back', events_path %>

app/views/events/show.html.erb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<p id="notice"><%= notice %></p>
2+
3+
<h1>Event Details</h1>
4+
5+
<p>
6+
<strong>Title:</strong>
7+
<%= @event.title %>
8+
</p>
9+
10+
<p>
11+
<strong>Description:</strong>
12+
<%= @event.description %>
13+
</p>
14+
15+
<p>
16+
<strong>Start Date:</strong>
17+
<%= @event.start_date.strftime("%B %d, %Y %I:%M %p") if @event.start_date.present? %>
18+
</p>
19+
20+
<p>
21+
<strong>End Date:</strong>
22+
<%= @event.end_date.strftime("%B %d, %Y %I:%M %p") if @event.end_date.present? %>
23+
</p>
24+
25+
<p>
26+
<strong>Registration Close Date:</strong>
27+
<%= @event.registration_close_date.strftime("%B %d, %Y %I:%M %p") if @event.registration_close_date.present? %>
28+
</p>
29+
30+
<p>
31+
<strong>Publicly Visible:</strong>
32+
<%= @event.publicly_visible? ? 'Yes' : 'No' %>
33+
</p>
34+
35+
<%= link_to 'Edit', edit_event_path(@event) %> |
36+
<%= link_to 'Back', events_path %>

config/routes.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
resources :workshop_log_creation_wizard
4646
resources :workshop_logs, only: [:show, :edit, :new, :create, :update]
4747

48+
resources :events
49+
resources :event_registrations, only: [:create] do
50+
collection do
51+
post :bulk_create
52+
end
53+
end
4854
resources :resources
4955

5056
get 'stories', to: 'resources#stories'

0 commit comments

Comments
 (0)