Why does Rails keep telling me unpermitted parameter even though I have permitted it?
Asked Answered
G

1

9

I have a Profile model that has the following:

  has_many :transcripts, dependent: :destroy
  accepts_nested_attributes_for :transcripts, allow_destroy: true

On my Transcript model, I have the following:

include TranscriptUploader[:attachment]

Which is a Shrine Uploader mount.

In my app/views/profile/_form.html.erb, I have the following:

    <div id="transcripts" class="text-center">
      <% if @profile.transcripts.any? %>
        <% @profile.transcripts.each do |transcript| %>
          <%= link_to "Click to view Transcript", transcript.url %>
        <% end %>
      <% end %>

      <%= f.simple_fields_for :transcripts do |transcript| %>
        <%= render 'transcript_fields', f: transcript %>
      <% end %>
      <br />
      <div class="links">
        <%= link_to_add_association 'Add Transcript', f, :transcripts, class: "btn btn-success add-transcript-button" %>
      </div>
    </div>

Then in my views/profiles/_transcript_fields.html.erb, I have the following:

<%= f.file_field :attachment, multiple: true, class: 'col-lg-4 form-control' %>

In my ProfilesController, I have the following:

# truncated for brevity
def profile_params
  params.require(:profile).permit(:id, :first_name, :last_name, :dob, :height, :weight, :bib_color, :attachment, :remove_transcript, :transcript_cache, transcripts_attributes: [:id, :url, :name, :attachment, :attachment_data, :remove_transcript, :url_cache, :_destroy])
end

So far so good, right?

But when I go to add a new profile, this is what my log looks like:

Started POST "/profiles" for ::1 at 2016-11-17 01:47:05 -0500
Processing by ProfilesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"JDMTXHFCIaB3TFmCOQ==", "profile"=>{"avatar"=>"", "first_name"=>"Jack", "last_name"=>"BeNimble", "dob(3i)"=>"17", "dob(2i)"=>"11", "dob(1i)"=>"1986", "transcripts_attributes"=>{"1479365203532"=>{"attachment"=>[#<ActionDispatch::Http::UploadedFile:0x007f8901918700 @tempfile=#<Tempfile:/var/folders/0f/0gn/T/RackMultipart20161117-29277-msvds1.pdf>, @original_filename="Some-Awesome-File.pdf", @content_type="application/pdf", @headers="Content-Disposition: form-data; name=\"profile[transcripts_attributes][1479365203532][attachment][]\"; filename=\"Some-Awesome-File.pdf\"\r\nContent-Type: application/pdf\r\n">], "_destroy"=>"false"}}, "commit"=>"Create Profile"}
  User Load (2.8ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Role Load (1.3ms)  SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 2]]
  Role Load (2.3ms)  SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'coach') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 2]]
  Role Load (2.5ms)  SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'player') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 2]]
   (3.9ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)) OR ((roles.name = 'coach') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 2]]
Unpermitted parameter: attachment
  Tournament Load (1.1ms)  SELECT "tournaments".* FROM "tournaments" WHERE "tournaments"."id" = 1
   (5.0ms)  SELECT COUNT(*) FROM "profiles" INNER JOIN "profiles_tournaments" ON "profiles"."id" = "profiles_tournaments"."profile_id" WHERE "profiles_tournaments"."tournament_id" = $1  [["tournament_id", 1]]
   (0.9ms)  BEGIN
   (1.5ms)  COMMIT
  Position Load (2.1ms)  SELECT "positions".* FROM "positions" WHERE 1=0
Unpermitted parameter: attachment
   (0.7ms)  BEGIN
  School Load (1.2ms)  SELECT  "schools".* FROM "schools" WHERE "schools"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Profile Exists (3.7ms)  SELECT  1 AS one FROM "profiles" WHERE ("profiles"."id" IS NOT NULL) AND "profiles"."slug" = $1 LIMIT $2  [["slug", "jack-benimble-st-george-s-college"], ["LIMIT", 1]]
  SQL (23.3ms)  INSERT INTO "profiles" ("first_name", "last_name", "dob", "bib_color", "created_at", "updated_at", "player_type", "school_id", "grade", "slug", "home_phone", "cell_phone", "email") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING "id"  [["first_name", "Jack"], ["last_name", "BeNimble"], ["dob", Mon, 17 Nov 1986], ["bib_color", ""], ["created_at", 2016-11-17 06:47:05 UTC], ["updated_at", 2016-11-17 06:47:05 UTC], ["player_type", 0], ["school_id", 1], ["grade", ""], ["slug", "jack-benimble-st-george-s-college"], ["home_phone", ""], ["cell_phone", ""], ["email", ""]]
  SQL (3.5ms)  INSERT INTO "transcripts" ("profile_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["profile_id", 46], ["created_at", 2016-11-17 06:47:05 UTC], ["updated_at", 2016-11-17 06:47:05 UTC]]
  Profile Load (2.8ms)  SELECT  "profiles".* FROM "profiles" WHERE "profiles"."id" = $1 LIMIT $2  [["id", 46], ["LIMIT", 1]]
  SQL (1.7ms)  INSERT INTO "profiles_tournaments" ("profile_id", "tournament_id") VALUES ($1, $2)  [["profile_id", 46], ["tournament_id", 1]]
   (2.6ms)  COMMIT
  Profile Store (150.2ms)  {"id":46}
  Profile Store (135.8ms)  {"id":46}
Unpermitted parameter: attachment
Redirected to http://localhost:3000/profiles/jack-benimble-st-george-s-college
Completed 302 Found in 499ms (Searchkick: 286.0ms | ActiveRecord: 91.8ms)

When I do this for the edit action also, I see something similar.

Notice that in my profile_params, I declare :attachment in two places. Both within a transcript_attributes hash, and in the normal list of attributes.

What could be causing this? What am I missing?

Edit 1

Updated params:

def profile_params
  params.require(:profile).permit(
    :id, :first_name, :last_name, :dob, :height, :weight,
    :bib_color, :parent_name, :sat_score, :video_url, :avatar,
    :remove_avatar, :avatar_cache, :player_type, :school_id, :grade, :email, 
    :cell_phone, :home_phone, tournament_ids: [], position_ids: [], 
    grades_attributes: [:id, :subject, :result, :grade_type, :_destroy], 
    achievements_attributes: [:id, :body, :achievement_type, :_destroy], 
    articles_attributes: [:id, :title, :url, :source, :_destroy], 
    videos_attributes: [:id, :url, :video, :vimeo_url, :vimeo_embed_code, :official, 
                        :video_cache, :remove_video, :_destroy], 
    transcripts_attributes: [:id, :url, :name, :attachment_data, :remove_transcript, 
                             :url_cache, :_destroy], 
    attachment: [])
end
Gaillard answered 17/11, 2016 at 7:27 Comment(4)
could you show how this partial looks : ` <%= render 'transcript_fields', f: transcript %>`Capeskin
Is attachment an array?Duckbill
@LukaszMuzyka That's spelled out above in that 1 line: views/profiles/_transcript_fields.html.erb.Gaillard
@Gaillard sorry missed that..Capeskin
D
16

For array values, you have to declare them as such. For array of simple strings it can be this.

.permit(:foo, :bar, ..., attachment: [])

If you had an array of objects, you could whitelist properties of the objects

.permit(:foo, :bar, ..., attachment: [:prop1, :prop3])

It's all in the docs, by the way: Hash and Array parameters.

Duckbill answered 17/11, 2016 at 7:47 Comment(21)
That's the thing, so I am using the Shrine gem to handle uploads. That requires that I add an attribute_data which is a text field on the model. So on my Transcript model, I have this: # attachment_data :text. That's why in my profile_params, I have transcripts_attributes: [:id, :url, :name, :attachment, :attachment_data, :remove_transcript, :url_cache, :_destroy]. Note the attachment in that list.Gaillard
@Gaillard I see the attachment in that list. I also see multi-select file input.Duckbill
For the heck of it, I added attachment: [] to the list of my permissible params, and it still doesn't work and still gives me the Unpermitted parameter: attachment error.Gaillard
@marcamillion: did you remove the other attachment? And restarted the server, just in case?Duckbill
Hrmm...no. Ok let me try that. Edit: Ok I just tried that.....same issue. Same error.Gaillard
Well, I guess you have to debug it. Now that you are armed with knowledge, should be easier.Duckbill
The issue is that I mounted include TranscriptUploader[:attachment] to my Transcript.rb model, and then added attachment_data :text on that model -- but I am adding the record from my profile/_form.html.erb.Gaillard
@marcamillion: yeah, this is getting waaaaaay too specific. And quite far from the original "why is this parameter not permitted?" :)Duckbill
That's the thing, everything you told me I know already. But this issue is not what you are saying. It's more than that. I have been debugging all of the standard stuff, hence the question. If you re-read the question you will see that I tried all of that stuff.Gaillard
@marcamillion: show me your updated strong params method, again?Duckbill
Refresh the question, I left all the attributes for completeness sake.Gaillard
@marcamillion: please care about the readers. 5000 char long string is very unreadable. That attachment is part of transcript attributes? If so, the attachment: [] goes into transcript attributes.Duckbill
My apologies for the unreadable string. I was just trying to move quickly before you left :). That being said, you were right. It did belong inside transcripts: []. I tried that and it worked like a charm. Thanks!Gaillard
So given that I added attachment_data as a text column to my Transcript model, should I also add :attachment_data inside the attachment hash? i.e. attachment: [:attachment_data], instead of putting :attachment_data within transcripts_attributes: [] alone?Gaillard
@marcamillion: nope, why would you want to do that?Duckbill
Ok fair enough. I wasn't sure.Gaillard
@marcamillion: it's easy. Shape of your strong params must agree with the shape of the data. If it doesn't, you get unpermitted params.Duckbill
Ugghh bro...you're not gonna believe this. The issue has raised it's head again. Seems it wasn't fixed. I had to remove multiple: true from the form_field and now it is giving me the same issue. Thoughts?Gaillard
@marcamillion: come on, isn't it obvious? BTW, there's link to the docs in the answer.Duckbill
It was fixed, but you broke it again :)Duckbill
Ok fair enough. I figured it out. I had to remove the array and just re-add :attachment to the transcripts_attributes hash.Gaillard

© 2022 - 2024 — McMap. All rights reserved.