1

I have the following class:

 class ArticlesController < ApplicationController
      def create
        article = Article.new(article_params) 
     
      end
      
      private
        def article_params
          params.permit(:name, :age, book: [])
        end  
    end

and I have a field called book that contains a collection followed by a hash [{...}], inside the hash object it can contain any random attribute, for example:

book_1 = 
    [
          {
            "id": "a1",
            "type": "Color",
            "title": "Live life cicle",
            "content": "image_intro.png"
           },
      ] 

book_2 =
      [
          {
            "id": "a2",
            "email": "example@gmail.com",
            "domain": "http://ddd.com"
           }
      ]
    ...

book_7
     [
          {
            "id": "a23",
            "width": "3px",
            "heigth": "5px",
            "exist": true
           }
      ]

What I would like is that every time I save a book, it can go through article_params no matter what attributes it contains within the hash, if you could help me please I would be grateful.

Jared Beck
  • 16,796
  • 9
  • 72
  • 97
Samuel Da Costa
  • 415
  • 3
  • 17
  • 1
    Docs: https://guides.rubyonrails.org/action_controller_overview.html#nested-parameters and https://github.com/rails/rails/blob/main/actionpack/lib/action_controller/metal/strong_parameters.rb#L67 and – Jared Beck Sep 03 '21 at 18:58
  • 1
    Does this answer your question? [Rails - Strong Parameters - Nested Objects](https://stackoverflow.com/questions/18436741/rails-4-strong-parameters-nested-objects) – Jared Beck Sep 03 '21 at 18:58
  • 1
    While @JaredBeck pointed you to the source I think the pertinent parts to your question are *"It's mandatory to specify the nested attributes that should be permitted. If you use `permit` with just the key that points to the nested attributes hash, it will return an empty hash."* (Line 1162) and *"Imagine a scenario where you have parameters representing a product name and a hash of arbitrary data associated with that product, and you want to permit the product name attribute and also the whole data hash"* in the Docs. – engineersmnky Sep 03 '21 at 20:01
  • 1
    This means that while you cannot just use `books: []` and have it accept anything in that array. You can use `books: {}` as long as your `books` value is `{"0" => { "id": "a1","type": "Color","title": "Live life cicle","content": "image_intro.png"} , "1" => {"id": "a2","email": "example@gmail.com","domain": "http://ddd.com"}}` etc. – engineersmnky Sep 03 '21 at 20:03

1 Answers1

1

ActionController::Parameters does not have a "wildcard" syntax to allow any nested hash keys. But it does have #permit! which is an acknowledgement that strong parameters is not the solution for every possible problem.

permit! completely circumvents whitelisting by setting the permitted attribute on the ActionController::Parameters instance.

It will also set the permitted attribute on any nested instances of ActionController::Parameters - ie nested hashes in the parameters.

This is a very sharp tool which should be used with care.

In this case you might want to just use it on the nested attributes:

params.permit(:name, :age).merge(
  books: params.dup.permit!.fetch(:books, [])
)
max
  • 96,212
  • 14
  • 104
  • 165
  • It should be noted that `.permit!` will also set the `permitted` attribute on any nested instances of `ActionController::Parameters` - ie nested hashes in the parameters. Use with caution. – max Sep 07 '21 at 12:24