Assigning id's from another table to input using nested forms in Rails 4 -
i'm few weeks in first experience rails / web development in general , have come across snag can't seem find on overflow or work out. feel i'm there not quite...
i'm developing staff site charity, , need categorize new staff members in order assign privileges each of them. currently, have staff new view creates new staff members, , have nested form type in add staff's department @ same time. however, @ moment new department generated every new member of staff. if created 2 staff department "admin", end 2 admin departments separate type_id's instead of them being assigned same. how assign staff's type/department create in form, assuming departments exist. in console this:
s = staff.create(staff_name: "john", staff_email: "john@example.com", password: "asdsadsad") t = type.create(department: "admin") s.types << t
so far models staff , types(categories) (irrelevant parts removed), in i've added accepts_nested_attributes_for:
class staff < activerecord::base has_many :staff_types has_many :types, through: :staff_types accepts_nested_attributes_for :types validates :staff_name, presence: true, length: { minimum: 5, maximum: 50} has_secure_password end class stafftype < activerecord::base belongs_to :staff belongs_to :type end class type < activerecord::base validates :department, presence: true, length: { minimum: 2, maximum: 25 } has_many :staff_types has_many :staffs, through: :staff_types end
my staff controller, in i've whitelisted type variables, follows:
class staffscontroller < applicationcontroller before_action :set_staff, only: [:edit, :update, :show] def new @staff = staff.new 1.times { @staff.types.build} end def create @staff = staff.new(staff_params) if @staff.save flash[:success] = "your account has been created successfully" redirect_to staff_path(@staff) else render 'new' end end private def staff_params params.require(:staff).permit(:staff_name, :staff_email, types_attributes: [:id, :department]) end end
and view following, in i've embedded nested form in form_for helper:
<div class="row"> <div class="well col-md-8 col-md-offset-2"> <%= form_for @staff |f| %> <%= f.label :staff_name %> <%= f.text_field :staff_name %> <%= f.label :staff_email %> <%= f.email_field :staff_email %> <%= f.label :password %> <%= f.password_field :password %> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation %> <%= f.fields_for :types, @staff.types |types_form| %> <%= types_form.label :department %> <%= types_form.text_field :department %> <% end %> <%= f.submit(@staff.new_record? ? "submit profile" : "submit edited profile", class: "btn btn-success") %> <% end %> </div> </div>
the reason new record created every time submit new staff member because don't let controller know staff member's type existing type. question is, best way go doing edit sentence
method #1: choose staff member types in multi-select
if have set number of types, you've inserted them, , don't need change them, can use multi-select. so, replace below code in code...
<%= f.fields_for :types, @staff.types |types_form| %> <%= types_form.label :department %> <%= types_form.text_field :department %> <% end %>
...with:
<%= f.collection_select :type_ids, type.all, :id, :department, { selected: @staff.type_ids }, { multiple: true, size: type.all.size } %>
and then, in controller, change staff_params
method to:
def staff_params params.require(:staff).permit(:staff_name, :staff_email, type_ids: []) end
using method, you'll able select multiple types each staff member out of possible types. assuming don't need create type when create staff member, i'd recommend going forward member.
you can use checkboxes rather multi-select, won't cover in answer. can read check boxes here.
method #2: determine types new in controller
if you'd keep ability type in staff member's type, it'll bit trickier, think can keep of logic in create
method of controller. currently, in method, save staff member grab parameters it. can first check if of types passed new (i.e. staff member hasn't yet been associated type), , if @ least 1 is, check if each existing type. update create
method read:
def create @staff = staff.assign_attributes(staff_params) @staff.staff_types.each_with_index |staff_type, index| if (type = type.find_by(department: staff_type.type.department)).present? @staff.staff_type[index].assign_attribute(:id, type.id) end end if @staff.save flash[:success] = "your account has been created successfully" redirect_to staff_path(@staff) else render 'new' end end
i should note there better way this, , answer encourages post better one, answer should work purposes.
Comments
Post a Comment