I have a Meeting model, view, and controller. Every Meeting, I would like to take attendance of the Members of the club. Each Meeting is also associated with a Tournament.
It seems ideal to me, that each Meeting Entry would store the Tournament_id and attendence for each Member_id. However, if you were to do this, you would need a dynamic column length for the member_ids (one column for each member), which can vary.
- Is that possible?
- If that is not the best way, what is the best way to store the data?
Currently, I have it where each Meeting.id stores 1 Member's Attendance and the form rolls out all Members for 1 given tournament and a check box for their attendance. However, I don't fully understand how that is working, and I can't figure out how to easily Edit the member's attendance that way.
I got part of the solution of my current functionality from here, but was trying to find out if there is another way to get it fully working.
Thanks
CodePudding user response:
It seems ideal to me, that each Meeting Entry would store the Tournament_id and attendence for each Member_id. However, if you were to do this, you would need a dynamic column length for the member_ids (one column for each member), which can vary.
Big nope. That's not a tenable solution for modeling data in a relational database as the schema would be completely unmaintable and you would end up with a huge amount of columns that almost entirely contain nulls. The SQL queries would also be very crazy.
You instead need to think in terms of each row in a table containing the unique data for each member. In database design this corresponds to the concept First Normal Form.
This is a simplefied example of how you would keep track of attendence*:
class Member
has_many :attendences
has_many :meetings, through: :attendences
end
class Meeting
has_many :attendences
has_many :members, through: :attendences
end
# rails g model attendence member:belongs_to meeting:belong
class Attendence < ApplicationRecord
belongs_to :member
belongs_to :meeting
end
Here attendences
is a join table containing the member and meeting ids and we have a many to many assocation between Member and Meeting.
You can then just use the rails form helpers for creating checkboxes from collections together with the member_ids
setter / getter created by has_many :members, through: :attendences
:
<%= form_with(model: @meeting) do |form| %>
<div >
<%= form.label :member_ids, 'Members in attendence' %>
<%= form.collection_checkboxes :member_ids, @available_members, :id, :name %>
</div>
# ...
<% end %>
In your controller you would then whitelist the member_ids
column with a hash key with an empty array as the value:
class MeetingsController < ApplicationController
def new
@meeting = Meeting.new
@available_members = Member.all
end
def create
@meeting = Meeting.new(meeting_params)
if @meeting.save
redirect_to @meeting
else
@available_members = Member.all
render :new
end
end
private
def meeting_params
params.require(:meeting)
.permit(:foo, :bar, :baz, member_ids: [])
end
end
This will permit an array of permitted scalar values such as a list of ids.