Rails strong params with "dot" in name - ruby-on-rails

I need to permit a parameter in Rails 4 which has a dot in it's name:
My params hash looks like the following:
{
"dictionary_objects.id" => [
"102", "110", "106"
]
}
I can get param value:
>> params['dictionary_objects.id']
=> [
[0] "102",
[1] "110",
[2] "106"
]
But when I try to permit it, it returns an empty hash:
>> params.permit('dictionary_objects.id')
Unpermitted parameters: dictionary_objects.id
=> {}
Does anybody know how can I permit params with a dot in it's name?
Thanks.

I think it's just failing to permit it because you've got a collection and you're telling it to permit a single value parameter. If you use:
params.permit(:'dictionary_objects.id' => [])
then all should be well.

for edge cases I recommend a very useful workaround:
params.slice('dictionary_objects.id').permit!
So you do whitelist keys and dont become crazy because of strong params.
sidenote:
rails is builtin to receive args like dictionary_object_ids for has_many relationships, you could leverage this instead.

Related

rename strong parameters rails 5

i have an issue with mapping third-party response to my server
the response is
"id": ".....",
"external_id": "....",
"recurring_payment_id": "....",
"is_high": ...,
"payment_method": "...",
and i set my strong params like
def invoice_params
params
.require(:invoice)
.permit({id: :invoice_id}, :external_id, :recurring_payment_id,
:payment_method)
end
i want to rename id to invoice_id
but i got an error
Unpermitted parameter: :id
I believe strong parameter does not support what you did. You need to work around it by rename the params key.
There is an easier method using alias, but use with caution. Add this to your class.
alias_attribute :id, :invoice_id
Edit: swap order because invoice_id is attribute in db
params[:id] = params.delete(:invoice_id)
params.permit(:id)
or
params[:invoice][:id] = params[:invoice].delete(:invoice_id)
params.require(:invoice).permit(:id)

Permitting array of hashes rails 5

My rails version is 5 and I have request param like this,
{ "segment": {
"name": "test",
"new_filters": [
{"criteria": "sad",
"other_keys": [{"key": "value"}]
},
{"criteria": "sad",
"other_keys1": [{"key1": "value1"}]
}]
}
}
I am stuck in permitting the new_filter params in rails controller,
I am trying below code,
params.require(:segment).permit(:name, :people_count, new_filters: [])
and still getting the error. But this is not the case while having array of strings in new_filter key.
Eg: ["sad", "asdasd"]. How to get the nested structure as whitelisted attribute?
This worked for me when testing with your attributes:
params.require(:segment).permit(:name, :people_count, new_filters: [:criteria, other_keys: [:key], other_keys1: [:key1]])
In your model file for segment try adding the line
accepts_nested_attributes_for :new_filters
this should allow you to pass those attributes.
https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Rails Strong Parameters either in root or nested object

I want to be able to support a set of parameters in either the root params object:
?foo=a
params.permit(:foo)
Or in a nested object:
?bar[foo]=a
params.require(:bar).permit(:foo)
I'm passing parameters into that controller from a form object, so the nested object happens naturally, but I'd like to also be able to pass the params in the root object in the query string and support both.
Is there an elegant, non-hacky way to accomplish this?
require is like [] with an exception when the value is missing (much like Hash#fetch). You can instead just use [] directly to get the nested structure if it's there, and fall back to the root params otherwise:
(params[:bar] || params).permit(:foo)
remember that require is different as permit.
The require method ensures that a specific parameter is present. is not necessary to use on nested ones, it makes sure that the required one come in the params or it will throw an error.
you can work with nested attributes like this
params = ActionController::Parameters.new({
person: {
name: "Francesco",
age: 22,
pets: [{
name: "Purplish",
category: "dogs"
}]
}
})
permitted = params.permit(person: [ :name, { pets: :name } ])
permitted.permitted? # => true
permitted[:person][:name] # => "Francesco"
permitted[:person][:age] # => nil
permitted[:person][:pets][0][:name] # => "Purplish"
permitted[:person][:pets][0][:category] # => nil
you can check the documentation on this here

Rails - permit a param of unknown type (string, hash, array, or fixnum)

My model has a custom_fields column that serializes an array of hashes. Each of these hashes has a value attribute, which can be a hash, array, string, or fixnum. What could I do to permit this value attribute regardless of its type?
My current permitted params line looks something like:
params.require(:model_name).permit([
:field_one,
:field_two,
custom_fields: [:value]
])
Is there any way I can modify this to accept when value is an unknown type?
What you want can probably be done, but will take some work. Your best bet is this post: http://blog.trackets.com/2013/08/17/strong-parameters-by-example.html
This is not my work, but I have used the technique they outline in an app I wrote. The part you are looking for is at the end:
params = ActionController::Parameters.new(user: { username: "john", data: { foo: "bar" } })
# let's assume we can't do this because the data hash can contain any kind of data
params.require(:user).permit(:username, data: [ :foo ])
# we need to use the power of ruby to do this "by hand"
params.require(:user).permit(:username).tap do |whitelisted|
whitelisted[:data] = params[:user][:data]
end
# Unpermitted parameters: data
# => { "username" => "john", "data" => {"foo"=>"bar"} }
That blog post helped me understand params and I still refer to it when I need to brush up on the details.

Rails - Parameter with multiple values in the URL when consuming an API via Active Resource

I am consuming an API that expects me to do requests in the following format:
?filter=value1&filter=value2
However, I am using Active Resource and when I specify the :params hash, I can't make the same parameter to appear twice in the URL, which I believe is correct. So I can't do this:
:params => {:consumer_id => self.id, :filter => "value1", :filter => "value2" }, because the second filter index of the hash will be ignored.
I know I can pass an array (which I believe is the correct way of doing it) like this:
:params => {:consumer_id => self.id, :filter => ["value1","value2"] }
Which will produce a URL like:
?filter[]=value1&filter[]=value2
Which to me seems ok, but the API is not accepting it. So my question are:
What is the correct way of passing parameters with multiple values? Is it language specific? Who decides this?
http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters
Try :filter[] => value, :filter[] => value2
to create a valid query string, you can use
params = {a: 1, b: [1,2]}.to_query
http://apidock.com/rails/Hash/to_query
http://apidock.com/rails/Hash/to_param
You can generate query strings containing repeated parameters by making a hash that allows duplicate keys.
Because this relies on using object IDs as the hash key, you need to use strings instead of symbols, at least for the repeated keys.
(reference: Ruby Hash with duplicate keys?)
params = { consumer_id: 1 } # replace with self.id
params.compare_by_identity
params["filter"] = "value1"
params["filter"] = "value2"
params.to_query #=> "consumer_id=1&filter=value1&filter=value2"

Resources