Jamaal
Jamaal

Reputation: 1499

Why am I getting an unpermitted parameters error in Rails using a nested form?

I have a little problem here where I am trying to make a form with nested attributes and I keep on getting an unpermitted parameters error. This is the code in the user.rb file:

class User < ActiveRecord::Base
    has_many :topics

    has_many :subjects, through: :topics
end

This is the code in the subject.rb file:

class Subject < ActiveRecord::Base
    has_many :topics
    has_many :users, through: :topics, dependent: :destroy
    accepts_nested_attributes_for :topics, reject_if: :all_blank, update_only: true,allow_destroy: true
    validates :name, presence: true
end

This is the code in the topic.rb file:

class Topic < ActiveRecord::Base
    belongs_to :subject
    belongs_to :user
    validates :name, presence: true
end

This is the code in my subjects_controller.rb:

class SubjectsController < ApplicationController
    before_filter :require_login

    def new
        @subject = current_user.subjects.build
        @subject.topics.build
    end

    def create
        @subject = current_user.subjects.build(subject_params)
        if @subject.save
            flash[:success] = "New subject created!"
            redirect_to user_path(@user)
        else
            flash[:error] = "Errors!!!"
            render :new
        end
    end

    private
    def subject_params
        params.require(:subject).permit(:name, topics_attributes: [:name,:user_id,:subject_id])
    end

end

This is my code in the view that creates the form:

<%= form_for @subject do |f| %>

    <%= f.label :name, "Subject" %><br>
    <%= collection_select :user, :subject_id, Subject.all, :id, :name %>

    <%= f.fields_for :topic do |t| %>

        <%= t.label :name, "Topic" %>
        <%= t.text_field :name %>

    <% end %>

    <div class="text-center"><%= f.submit class: "button radius" %></div>

<% end %>

This is my topics_controller.rb:

class TopicsController < ApplicationController
    before_filter :require_login
    before_action :find_subject

    def new
        @topic = @subject.topics.build
    end

    def create
        @topic = @subject.topics.build(topic_params)
        @topic.user_id = current_user.id
        if @topic.save
            flash[:success] = "Success!"
        else
            flash[:error] = "Error!"
        end
    end

    private
    def topic_params
        params.require(:topic).permit(:name,:subject_id,:user_id)
    end

    def find_subject
        @subject = Subject.find(params[:subject_id])
    end
end

I am thinking the reason why I am getting an Unpermitted parameters: topic error is because I'm not passing in the "user_id" or "subject_id" upon submission of the form. If this is the case how would I do this with a hidden form field? Or does anyone have any other suggestions as to where I may be going wrong?

This is the server log for what's currently happening:

Processing by SubjectsController#create as HTML
Processing by SubjectsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"o42ESf7kQ4R3pB6CUvcEetmqoZOmIK8V4UrVTQ5BW/M=", "user"=>{"subject_id"=>"1"}, "subject"=>{"topics_attributes"=>{"0"=>{"name"=>"something"}}}, "commit"=>"Create Subject"}
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"o42ESf7kQ4R3pB6CUvcEetmqoZOmIK8V4UrVTQ5BW/M=", "user"=>{"subject_id"=>"1"}, "subject"=>{"topics_attributes"=>{"0"=>{"name"=>"something"}}}, "commit"=>"Create Subject"}
  User Load (1.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 2]]
  User Load (1.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 2]]
   (0.2ms)  BEGIN
   (0.2ms)  BEGIN
   (0.3ms)  ROLLBACK
   (0.3ms)  ROLLBACK

Upvotes: 2

Views: 1124

Answers (2)

Michael Durrant
Michael Durrant

Reputation: 96544

Try changing Subject from

has_many :subjects, through: :topics, dependent: :destroy

to

has_many :users, through: :topics

Upvotes: 0

Kirti Thorat
Kirti Thorat

Reputation: 53038

Update the fields_for in view as below:

<%= f.fields_for :topics do |t| %>

    <%= t.label :name, "Topic" %>
    <%= t.text_field :name %>

<% end %>

As you have a One to Many relationship setup between Subject and Topic, you must use plural topics as fields_for argument.

Upvotes: 1

Related Questions