Rails "Strong Parameters", how to permit and require multiple params

Hello,

I have a hierarchical hash from a view

{
  "utf8"=>"✓",
  "authenticity_token"=>"...",
  "article"=>{
    "title"=>"Titel Tags",
    "text"=>"Tags Tags Tags"
  },
  "tags"=>{
    "name"=>"ufos, foo, baz, bar"
  },
  "commit"=>"Create Article"
}

In my controller, my approach is with tap

def article_params
params.tap { |article_params| article_params.require(:article).permit(:title, :text)}.tap {|tags_params| tags_params.require(:tags).permit(:name) }
end

But it doesn’t work.

I can’t params.require(...).permit(...) the hash a second time. It will only work for the last time.
So if I do params.require(:articles).permit(...) as well as params.require(:tags).permit(...) it will only accept the second expression.

Thank you very much in advance

von Spotz

btw: this is my first post. Is there a way to turn off this red “Check out our new jobs section…” banner in the right bottom corner?

So as the require documentation says, when passed a single key … returns it’s associated values. So yes, it is expected to chunk information that you will not have downstream in the tap chain.

But, “When given an array of keys, the method tries to require each one of them in order. If it succeeds, an array with the respective return values is returned”.

In your case:

article_params, tags_params = params.require([:article, :tags])
user_the_article_params_for_something(article_params.permit(:title, :text))
use_the_tags_params_for_something(tags_params.permit(:name))

Or you could build the full permited hash from the pieces:

article_params, tags_params = params.require([:article, :tags])
{
  article: article_params.permit(:title, :tex),
  tags: tags_params.permit(:name)
}.permit!

Notice I’m using the last permit! that says: Permit it all. But at this moment, I have full control of what I’m building so it is OK.

1 Like

Thanks for your approach. Sadly I get the following error:

# undefined method permit!’ for #Hash:0x00007fe8d0206370`

I made a slight modification on your approach and instead of a Hash I take a “new” Action Controller Parameters and give the both objects as parameters to this one.
It seems to work.

  article_params, tags_params = params.require([:article, :tags])
  
  article_tags_params = ActionController::Parameters.new( {
  article: article_params.permit(:title, :text, :id, :parent_article_id),
  tags: tags_params.permit(:name)
  }).permit!

Thank you very much !

1 Like

Good.

A simplier way :smiley:

params.permit(article:[ :title, :text], tags: [:name])
1 Like