I've been working on a simple scenario : users can join one group of each type. I am tring to build a form that will show all types, and under each type's name- the chosen group for that type, or a select box to choose a group of that type, if the user is not a member of one.
So far, I only could come up with a seperate form for each type - rather unconvinient. I'v Been tring to solve this for several days. I found explanations for uniqness of instances, collection_select and has_many through forms but I can't find a way to a combine solution.
Models:
class User < ActiveRecord::Base
has_many :memberships
has_many : groups, through: :memberships
end
class Group < ActiveRecord::Base
has_many : memberships
has_many :users, through: :memberships
belongs_to :group_type
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
validates :user_id, uniqueness: { scope: [:group_id, :group_type] }
end
class GroupType < ActiveRecord::Base
has_many :groups
end
View:
<% @types = GroupTypes.all %>
<% @types.each do |type| %>
<%= '#{@type.name}' %>
<% @active_group = user.groups.where(type :type) %>
<% if @active_group.exist? %>
<%= '#{@active_group}' %>
<%= link_to 'Leave', [group.user], method: :delete, data: { confirm: 'Are you sure?' } %>
<% else %>
<%= form_for (Membership.new) do |f| %>
<%= f.hidden_field :user_id, value: @user.id %>
<%= f.collection_select :group_id, Groups.all.where(type :type), :id, :name
<%= f.submit %>
<%end>
<%end>
<%end>
controlller:
Class MembershipController < ApplicationController
def create
@user = User.find(params[:user_id])
@group = Group.find(params[:group_id])
@membership = user.membership.create(group :@group )
@user. memberships << membership
redirect_to user_register_path
end
def destroy
@user = User.find(params[:user_id])
@user.groups.find_by(group : params[:group_id]).delete
redirect_to user_register_path
end
private
def membership_params
params.require(:membership).permit(:user_id, :group_id)
end
end
Not sure if it is working properly, but as I wrote I am not happy with the idea of a form for each cathegory. was wondering if anyone could advise on a solution for that basic problem.
Thanks!
not a complete answer but I thought of posting
the whole idea is by DRYING up your code you can easily see solution to your problems
class Group < ActiveRecord::Base
has_many : memberships
has_many :users, through: :memberships
has_many :types, class_name: "Group",
foreign_key: "type_id"
belongs_to :type, class_name: "Group"
end
migration
class CreateTypes < ActiveRecord::Migration[5.0]
def change
create_table :groups do |t|
t.references :type, index: true
t.timestamps
end
end
end
2) your controller#new
def new
@active_groups = current_user.groups.map{ |group| group.types}
@types = Type.all
end
3) use form helpers
def user_group?
type.group.user == current_user
end
4) DRY your form
<% @types.each do |type| %>
<%= '#{@type.name}' %>
<% if user_group? %>
// show your form
<%end>
// etc etc
<%end>
also I never use this architecture, of showing the child form and using it to query for the parent, but usually I always start from the parent and build a nested form