8
votes

How to permit/white-list deep-nested hashes with very un-regular (impossible to declare) structure.

Example:

{"widgets" => [
  {
    "id" => 75432,
    "conversion_goal_id" => 1331,
    "options" => {"form_settings"=>{"formbuilder-bg-color"=>"rgba(255, 255, 255, 0)", "font-size"=>"14px", "form-field-depth"=>"42px"}, "linkedWidget"=>""},
    "type" => "formbuilder-widget"
  },
  {
    "id" => 75433,
    "conversion_goal_id" => nil,
    "options" => {"width"=>"200px", "height"=>"185px", "display"=>"block", "left"=>313, "top"=>152, "position"=>"absolute"},
    "type" => "social-sharing-widget"
  },
  {},
]}

So options JSON/hash object doesn't have any specified structure.

It is formless.

It can be something like

{"width"=>"200px", "height"=>"185px", "display"=>"block", "left"=>313, "top"=>152, "position"=>"absolute"}

OR:

   {"form_settings"=>{"formbuilder-bg-color"=>"rgba(255, 255, 255, 0)", "font-size"=>"14px", "form-field-depth"=>"44px"},
    "linkedWidget"=>"",
    "required_height"=>164,
    "settings"=>
     [{"field_options"=>{"include_other_option"=>true, "size"=>"large", "view_label"=>false},
       "field_type"=>"text",
       "label"=>"Name:",
       "required"=>false,
       "asterisk"=>false,
       "textalign"=>"left"},
      {"field_options"=>{"include_other_option"=>true, "size"=>"large", "view_label"=>false},
       "field_type"=>"email",
       "label"=>"Email:",
       "required"=>false,
       "asterisk"=>false,
       "textalign"=>"left"},
      {"buttonalign"=>"left",
       "buttonbgcolor"=>"#ba7373",
       "buttonfont"=>"Old Standard TT",
       "buttonfontweight"=>"bold",
       "buttonfontstyle"=>"normal",
       "buttonfontsize"=>"18px",
       "buttonheight"=>"46px",
       "buttontxtcolor"=>"#ffffff",
       "field_options"=>{"include_other_option"=>true, "size"=>"large", "view_label"=>false},
       "field_type"=>"button",
       "label"=>"START LIVING",
       "required"=>true,
       "textalign"=>"left"}]}

Widgets node is just Array.

I didn't found any info how to whitelist nested attributes within array of hashes.

How to do this?

I found some info in documentation that I can specify keys directly,

page_params.permit({widgets: [:key1, :key2]})

But this won't work, since I want to permit ALL attributes/keys within options hash.

This solution, also doesn't support arrays, but it allows to white-list nested objects:

params.require(:screenshot).permit(:title).tap do |whitelisted|
  whitelisted[:assets_attributes ] = params[:screenshot][:assets_attributes ]
end

So how I can whitelist in every single element options attribute (array of hashes)?


REPLY TO COMMENTS:

  1. I need to allow everything within options attribute in widget node. Widget node is in widgets array. I still need to prevent other fields e.g. link_text, 'text_value' etc in array - I don't want them to be submitted.

  2. I need strong parameters to whitelist used parameters and backlist not used parameters. Some parameters exist only in front-end and don't exist in back-end. If I submit everything - then I will have exception.

1
What are you doing with the options attribute? Strong params is generally used when doing mass assignment.jvillian
options field is used for saving OPTIONS specific to given widget. Different widget have different options, so it is formless.nothing-special-here
Can't believe almost 4 years after this question was posted, there still doesn't seem to be a way to accomplish this with an array of deeply nested dynamic hashes.yuяi
Couldn't you just JSONify the options value on the frontend before sending and then JSON.parse on the backend?Scott Schupbach

1 Answers

-4
votes

Maybe I don't follow what you're trying to do here. Strong params are to prevent a user from submitting malicious data, so it basically whitelists certain keys. If you want to allow for everything, what do you need strong params for?