Reputation: 740
So I have the following models. User, Team & Membership with the following definitions
User
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :current_team, class_name: "Team", optional: true
has_many :memberships
has_many :teams, through: :memberships
has_many :owner_memberships, -> { where(role: :owner) }, class_name: "Membership"
has_many :owned_teams, through: :owner_memberships, source: :team
def membership_for(team)
memberships.where(team: team).take
end
end
Team
class Team < ApplicationRecord
has_many :memberships
has_many :users, through: :memberships
has_one :owner_membership, -> { where(role: :owner, status: :active) }, class_name: "Membership"
has_one :owner, through: :owner_membership, source: :user
end
Membership
class Membership < ApplicationRecord
belongs_to :user
belongs_to :team
end
All of the forms generated using scaffold work fine. The issue I am now facing is that I have added 2 extra fields to the Membership model, Role
& Status
meaning the membership class now looks like the below but I am struggling to pass this these fields to the database.
class Membership < ApplicationRecord
belongs_to :user
belongs_to :team
enum status: [:pending, :active]
enum role: [:owner, :admin, :user]
def owner_or_admin?
owner? || admin?
end
end
When I look at the console for rails s
I can see the following which would suggest that the new fields aren't getting sent as part of the membership definition but as separate parameters. How do I get them to send and create properly
Processing by MembershipsController#create as HTML
Parameters: {
"authenticity_token"=>"5gzC/7YLIzqb+uNqHi2izth07MPv4WXrF49444+2bK7ML7ceLwk+BR2tP9fHiqCVJFJrxJHjuaz7dXxcp0yq0A==",
"membership"=>{"user_id"=>"2", "team_id"=>"1"},
"role"=>"0",
"status"=>"0",
"commit"=>"Create Membership"
}
Membership Create (1.3ms) INSERT INTO "memberships" ("user_id", "team_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["user_id", 2], ["team_id", 1], ["created_at", "2021-08-30 14:58:03.929323"]
<%= form_with(model: membership, local: true) do |form| %>
<% if membership.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(membership.errors.count, "error") %> prohibited this membership from being saved:</h2>
<ul>
<% membership.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :user_id %>
<%= form.collection_select :user_id, User.order(:email),:id,:email, include_blank: true %>
</div>
<div class="field">
<%= form.label :team_id %>
<%= form.collection_select :team_id, Team.where(id: current_team.id),:id,:name, :selected => current_team %>
</div>
<div class="field">
<%= form.label :role %>
<%= select_tag :role, options_for_select(Membership.roles.map {|k, v| [k.humanize.capitalize, v]}) %>
</div>
<div class="field">
<%= form.label :status %>
<%= select_tag :status, options_for_select(Membership.statuses.map {|k, v| [k.humanize.capitalize, v]}) %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Upvotes: 0
Views: 84
Reputation: 102036
First setup a method that gives you the enum states as an array of [label, value]
pairs suitible for building selector, checkboxes or radio buttons:
module EnumHelper
# creates an array of [label, value] pairs from an enum
# the translations can be customized through for example:
# - membership.statuses.active
# - membership.roles.active
def options_from_enum(klass, name)
i18n_scope = "#{klass.model_name.i18n_key}.#{name}"
klass.public_send(name).map do |key|
label = I18n.t(
key,
default: key.to_s.humanize
scope: i18n_scope
)
[label, key]
end
end
end
Note that the value that you pass from a form should be the name of the enum state ("pending") and not the integer ("0") which is an internal implementation detail which should only be known to the model.
Then make sure you create the inputs off the form builder:
<%= form_with(model: @membership) do |form| %>
<div class="field">
<%= form.label :role %>
<%= form.select :role, options_from_enum(Membership, :roles) %>
</div>
<div class="field">
<%= form.label :status %>
<%= form.select :status, options_from_enum(Membership, :statuses) %>
</div>
# ...
<% end %>
Upvotes: 1