Rails Strong Params, Accept Multiple Data Types
Asked Answered
D

3

5

Is there any way to allow Rails strong params to permit different data types? For example, I'm using react-bootstrap-typeahead and redux-form to create a form that allows users to select from provided values or create their own value. The provided values come from the database and are handed to the controller as an object with name and id whereas the user created values are passed as a string.

Detta answered 9/4, 2017 at 23:27 Comment(2)
can you show some example of the kind of params you want to accept?Newhouse
gladly. in my case, the two possible options passed to the controller would be {id: 1, name: "Bob"} or "Sam". in the controller, including person: [:id, :name] conforms with the first scenario and :person conforms with the second, but I need a solution that works with bothDetta
F
4

Permitting both a String and Array/Object in Rails 4+

TL;DR: Simply list parameter multiple times to support different types.

  • String or Array: params.require(:my_model).permit(:my_attr, my_attr: [])
  • String or Object: params.require(:my_model).permit(:my_attr, my_attr: [:key1, :key2])

Full Example

Suppose we have a model MyModel which has an attribute my_attr.

my_attr can be a string or array:

# example requests: 
#   - {"my_model": {"my_attr": "hello" }
#   - {"my_model": {"my_attr": ["hello", "world"] }
params.require(:my_model).permit(:my_attr, my_attr: []) 

my_attr can be a string or object:

# my_attr can be a string or an object with keys key1, key2
# example requests: 
#   - {"my_model": {"my_attr": "hello" }
#   - {"my_model": {"my_attr": { "key1": "val1", "key2": "val2" }
params.require(:my_model).permit(:my_attr, my_attr: [:key1, :key2])

The first argument to permit allows my_attr to be a string, the second allows it to be an array or object (see documentation for Rails parameters).

Testing In Rails Console

Copy/Paste the following code to experiment with params directly:

# Testing with String
params = ActionController::Parameters.new(my_model: { my_attr: "My String" })
permitted = params.require(:my_model).permit(:my_attr, my_attr: [])
permitted.permitted?      # => true

# Testing with Array
params = ActionController::Parameters.new(my_model: { my_attr: ["Hello", "World"] })
permitted = params.require(:my_model).permit(:my_attr, my_attr: [])
permitted.permitted?      # => true

# Testing with Object
params = ActionController::Parameters.new(my_model: { my_attr: {key1: 'attr1', key2: 'attr2' }})
permitted = params.require(:my_model).permit(:my_attr, my_attr: [:key1, :key2])
permitted.permitted?      # => true
Foucquet answered 16/3, 2022 at 18:39 Comment(0)
P
3

I recently did something like

params.require(:note).permit(
  fields: [:value, value: []]
)

which allowed me to submit string and array params.

Sorry I don't have the docs to back me up on that, I'm just learning ruby myself. Hope this helps.

Phonics answered 2/8, 2018 at 20:50 Comment(0)
P
0

A form's submitted values will be stored in params[:object] regardless. I'm still not sure what you're asking - can you post your create controller actions if that's what being called on submit?

Pressroom answered 10/4, 2017 at 1:43 Comment(2)
inside #example_params: params.require(:example).permit(:description, :burst_date, :citation_url, categories: [:id, :name]) < this only works if categories is an object, not a string, which is my issueDetta
How about an if statement to test if the submitted value is a string -- if example[:obj].String? then covert to symbol -- example[:obj].to_symPressroom

© 2022 - 2025 — McMap. All rights reserved.