rename strong parameters rails 5 - ruby-on-rails

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)

Related

How can I store random nested variables with strong params methods in Rails?

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.
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, [])
)

Rails 4.2.5, simple_form, hstore, nested forms - Hstore Hash not persisting on save

I'm struggling to understand what's going on when I save my large-ish form - none of the Hstore parameters are saved to the database. Can someone point out what I presume to be the obvious error? (I've quickly trimmed a lot of the output to keep it concise as possible.
There's no console output, and it's not complaining about unpermitted params or anything. equipment field on the discipline model is the hstore column.
Given my strong params settings:
params.require(:profile).permit(
:id,
:user_id,
:gender,
:dob,
..snip..
disciplines_attributes: [
:id,
:profile_id,
:discipline_type,
:distance_in_meters_per_week,
..snip..
:equipment => [
:time_trial_bike,
:road_bike,
:turbo_trainer,
:watt_bike
]
]
My params:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XX", "profile"=>
{"gender"=>"male", "dob(1i)"=>"1927", "dob(2i)"=>"3", "dob(3i)"=>"14",
"disciplines_attributes"=>{"0"=>
{"discipline_type"=>"swimming", "distance_in_meters_per_week"=>"",
"equipment"=>
{
"pull_buoy"=>"true",
"paddles"=>"false",
"wetsuit"=>"true",
"fins"=>"false",
"tempo_trainer"=>"false"
}}},
"commit"=>"Create Profile"}
Then my inspected resultant profile_params from the controller:
{"gender"=>"male", "dob(1i)"=>"1927", "dob(2i)"=>"3", "dob(3i)"=>"14", "height_in_meters"=>"",
"disciplines_attributes"=>{"0"=>{"discipline_type"=>"swimming", "distance_in_meters_per_week"=>"",
"equipment"=>{
"pull_buoy"=>"true",
"paddles"=>"false",
"wetsuit"=>"true",
"fins"=>"false",
"tempo_trainer"=>"false"}}
}
Can someone help me understand why the equipment hash is not committed to the database?
Discipline id: 148, profile_id: 50, discipline_type: "running", distance_in_meters_per_week: "", sessions_per_week: nil, time_per_session_in_minutes: nil, created_at: "2017-03-14 12:02:15", updated_at: "2017-03-14 12:02:15", equipment: nil>]
What is it about writing your own question, that always then leads you to finally understanding that, just maybe, you screwed up elsewhere?
Like overloading the Disciplines::initialize method to 'seed' the equipment hstore when it's a new record. But doing it on every instance, not just new records.
So in answer to my own question. The above does work, and if I'd bothered to check the DB directly, rather than relying on the console, I might have realised that:
after_initialize :setup_equipment
def initialize(search, options = {})
self.options = options
super
end
private
def setup_equipment
self.equipment = self.options
end
Was my problem all along. :(

Rails strong params with "dot" in name

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.

Rails - Strong Parameters - Nested Objects

I've got a pretty simple question. But haven't found a solution so far.
So here's the JSON string I send to the server:
{
"name" : "abc",
"groundtruth" : {
"type" : "Point",
"coordinates" : [ 2.4, 6 ]
}
}
Using the new permit method, I've got:
params.require(:measurement).permit(:name, :groundtruth)
This throws no errors, but the created database entry contains null instead of the groundtruth value.
If I just set:
params.require(:measurement).permit!
Everything get's saved as expected, but of course, this kills the security provided by strong parameters.
I've found solutions, how to permit arrays, but not a single example using nested objects. This must be possible somehow, since it should be a pretty common use case. So, how does it work?
As odd as it sound when you want to permit nested attributes you do specify the attributes of nested object within an array. In your case it would be
Update as suggested by #RafaelOliveira
params.require(:measurement)
.permit(:name, :groundtruth => [:type, :coordinates => []])
On the other hand if you want nested of multiple objects then you wrap it inside a hash… like this
params.require(:foo).permit(:bar, {:baz => [:x, :y]})
Rails actually have pretty good documentation on this: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit
For further clarification, you could look at the implementation of permit and strong_parameters itself: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247
I found this suggestion useful in my case:
def product_params
params.require(:product).permit(:name).tap do |whitelisted|
whitelisted[:data] = params[:product][:data]
end
end
Check this link of Xavier's comment on github.
This approach whitelists the entire params[:measurement][:groundtruth] object.
Using the original questions attributes:
def product_params
params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
whitelisted[:groundtruth] = params[:measurement][:groundtruth]
end
end
Permitting a nested object :
params.permit( {:school => [:id , :name]},
{:student => [:id,
:name,
:address,
:city]},
{:records => [:marks, :subject]})
If it is Rails 5, because of new hash notation:
params.permit(:name, groundtruth: [:type, coordinates:[]]) will work fine.

Rails 4 Unpermitted Parameters for Array

I have an array field in my model and I'm attempting to update it.
My strong parameter method is below
def post_params
params["post"]["categories"] = params["post"]["categories"].split(",")
params.require(:post).permit(:name, :email, :categories)
end
My action in my controller is as follows
def update
post = Post.find(params[:id]
if post and post.update_attributes(post_params)
redirect_to root_url
else
redirect_to posts_url
end
end
However, whenever I submit the update the post, in my development log I see
Unpermitted parameters: categories
The parameters passed through is
Parameters: {"utf8"=>"✓", "authenticity_token"=>"auth token", "id"=>"10",
"post"=>{"name"=>"Toni Mitchell", "email"=>"eileen_hansen#hayetokes.info", "categories"=>",2"}}
I want to think it has something to do with the fact that the attribute categories is an array since everything else looks fine. Then again, I could be wrong. So, what's wrong with my code and why is not letting me save the categories field when clearly it is permitted to do so? Thanks.
Try this
params.require(:post).permit(:name, :email, :categories => [])
(Disregard my comment, I don't think that matters)
in rails 4, that would be,
params.require(:post).permit(:name, :email, {:categories => []})
The permitted scalar types are String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile and Rack::Test::UploadedFile.
To declare that the value in params must be an array of permitted scalar values map the key to an empty array:
params.permit(:id => [])
This is what the strong parameters documentation on Github says:
params.require(:post).permit(:name, :email, :categories => [])
I hope this works out for you.
I had the same problem, but simply adding array to permit was not enough. I had to add type, too. This way:
params.require(:transaction).permit(:name, :tag_ids => [:id])
I am not sure if this is perfect solution, but after that, the 'Unpermitted parameters' log disappeared.
I found hint for that solution from this excellent post: http://patshaughnessy.net/2014/6/16/a-rule-of-thumb-for-strong-parameters
If there are multiple items and item_array inside parameters like this-
Parameters {"item_1"=>"value 1", "item_2"=> {"key_1"=> "value A1",
"key_2"=>["val B2", "val C3"]} }
There we have array inside item_2.
That can be permit as below-
params.permit(item_2: [:key_1, :key_2 => [] ])
Above saved my day, may be helpful for you too.
I had the same problem but in my case I had also to change from:
<input type="checkbox" name="photographer[attending]" value="Baku">
to:
<input type="checkbox" name="photographer[attending][]" value="Baku">
Hope this is helping someone.

Resources