Search code examples
ruby-on-railsnested-formshas-manycocoon-gem

Rails nested form - refactor create action | cocoon gem


Everything is working fine but I want to change the code in create action to something like in update action. Right now, in the create action I am looping through all the values and saving them, but want to do it in a single line.

I have a College model.

class College< ActiveRecord::Base
   has_many :staffs, dependent: :destroy
   accepts_nested_attributes_for :staffs, reject_if: :all_blank, allow_destroy: true
end

And this is my Staff.rb

class Staff < ActiveRecord::Base
  belongs_to :college
end

And these are my Staffs controller create and update actions

def create
  @college= College.find(params[:college][:id_college_profile]
  )
  staff_params = params[:college][:staffs_attributes].values
  staff_params.each do |staff_param|
    @staff = @college.staffs.new
    @staff.name = staff_param[:name]
    @staff.designation = staff_param[:designation]
    @staff.experience = staff_param[:experience]
    @staff.specialization = staff_param[:specialization]
    @staff.save
  end
  redirect_to dashboard_path(id: @college.id), notice: "Successfully added Staff."
end

def update
  @college= College.find(params[:college][:id_college]
  )
  @college.update_attributes(staff_parameters)
  redirect_to root_path
end

These are strong parameters

def staff_parameters
  params.require(:college).permit(:id, staffs_attributes: [:id,  :name, :specialization, :experience, :designation, :_destroy])
end

Is there a way to save all of staffs in create action, without looping through all the values, but save all of them with a single line of code as in update action?

I have tried this in the StaffsController create action

def create
  @college= College.find(params[:college][:id_college]
  )
  @staff= @college.staffs.new(staff_parameters)
  @staff.save

  redirect_to dashboard_path(id: @college.id), notice: "Successfully added Staffs."
end

But it threw this error

unknown attribute 'staffs_attributes' for Staff.

Can someone kindly help me with this issue?


Solution

  • This is a CollegesController so I am assuming the create action also creates the new college?

    So in that case your create action should simply be something like:

    def create
      @college = College.new(staff_parameters)
      if @college.save
        # succesfully created
      else
        # there was a validation error
      end
    end 
    

    Note that in general we would use college_parameters because the root element is college and that you not only edit the nested staff, but also possibly attributes from college.

    If the college always already exists (because you are doing a find), it is a bit confusing to me what the difference is between create and update and why not always render the edit action in that case?

    I have a demo-project show-casing cocoon and nested attributes.