3

I am trying to create a nested form_for with a nested resource on Rails 4.0.3 However I've come to some problems and have spent quite a lot of time on it.

The problem is when I tried to submit the forms, the values are not save in my database. It will redirect straight through the labs#index

I have defined nested resources and labs_controller as follows.

route.rb

...    
resources :users do
  resources :labs
end

labs_controller.rb (part of it)

class LabsController < ApplicationController
  load_and_authorize_resource

  def new
    @user = User.find(params[:user_id])
    @lab  = Lab.new
  end

  def create
    @lab = Lab.new(lab_params)
    if @lab.save
      flash[:notice] = "Successfully created lab."
      redirect_to user_labs_url
    else
      render :action => 'index'
    end     
  end

  private

    def lab_params
      params.require(:lab).permit(:title, :description, 
        stages_attributes: [:id, :lab_id, :description, 
          tasks_attributes: [:id, :stage_id, :detail, :instruction, :answer ]])
    end
end

I have 3 models, Lab, Stage and Task and each one are linked through has_many relationship. I also use CanCan to handle the authorization.

lab.rb

class Lab < ActiveRecord::Base
  belongs_to :user
  has_many :stages
  resourcify

  validates :user_id, presence: true
  accepts_nested_attributes_for :stages
end

stage.rb

class Stage < ActiveRecord::Base
  belongs_to :lab
  has_many :tasks
  resourcify

  accepts_nested_attributes_for :tasks, allow_destroy: true
end

task.rb

class Task < ActiveRecord::Base
  belongs_to :stage
  resourcify

end

Here's my form partials.

_form.html.erb

<%= form_for [@user, @lab] do |f| %>
  <div class="field">
    <%= f.label :title %>
    <%= f.text_field :title %>
    <%= f.label :description%>
    <%= f.text_area :description %>
  </div>

  <%= f.fields_for :stages do |builder| %>
    <%= render "labs/partials/stage_fields", f: builder %>
  <% end %>

  <div><%= f.submit "Submit", class: "btn btn-primary" %></div>
<% end %>

_stage_fields.html.erb

<fieldset>
  <%= f.label :description %>
  <%= f.text_area :description %>
</fieldset>

<%= f.fields_for :tasks do |builder| %>
  <%= render "labs/partials/task_fields", f:builder %>
<% end %>

_task_fields.html.erb

<fieldset>
  <%= f.label :detail %>
  <%= f.text_area :detail %>
  <%= f.label :instruction %>
  <%= f.text_area :instruction %>
  <%= f.label :answer %>
  <%= f.text_field :answer %>
</fieldset>

I've gone through several questions and none of it is working for me. Eg.

I also try to follow Ryan Bates on Nested Model Form and still no luck. Hope someone could help me.

Thanks in advance!

Community
  • 1
  • 1
Faiz Mokhtar
  • 938
  • 1
  • 10
  • 24
  • try accessing builder in your partials and not f maybe? or try doing it without the partials and just triple nested in one form, maybe the partials are causing the problem – flylib Jun 12 '14 at 02:34
  • @flylib Hi, I've manage to fix the partial not rendering. It's just some wrong partial path that I've overlooked. But I still can't figure out why it's not saving to the database. – Faiz Mokhtar Jun 12 '14 at 07:39
  • Can you post your `log information` when submitting the `form`? – Pavan Jun 12 '14 at 10:21
  • @Pavan I've created a pastebin for the log. http://pastebin.com/rAB4JyMj. I've noticed that it says `Unpermitted parameters: stage`. Did I declare it wrongly? – Faiz Mokhtar Jun 12 '14 at 10:24

1 Answers1

1

Looking at the error logs it is probably a problem with your lab_params function. When you look at the Parameters that are passed in you want to match those with your permit options. Then check out the strong params docs for guidance on how to handle nested params.

   def lab_params
      params.require(:lab).permit(:title, :description,
        :stage => [:id, :lab_id, :description,
          :tasks => [:id, :stage_id, :detail, :instruction, :answer ]
        ]
      )
    end

I think this should get you beyond that error.

Bryan Clark
  • 2,542
  • 1
  • 15
  • 19