I have a parameter that can be either a string or a hash (metadata) and I would like to allow both using rails strong params
the problem is that metadata can either be a hash or a String or both
{transactions: [{metadata: "hello"}, metadata: {name: "world"}]}
With the rails params
params.permit(:transactions => [:reference_id, :metadata => ["name"]])
I have the following error
expected Hash (got String) for param `metadata'
I see the only way to permit, is to verify the constant parameters at first, then verify a parameter with variable type:
params.permit(:transactions => [:reference_id, :metadata])
begin
params.permit(:metadata => {})
rescue TypeError
# here check that :metadata is a string
end
Related
I'm having trouble with parameters in an app upgraded from 4.2 to 5.1. I have permitted my parameters, but as the documentation states, I'm getting back an object for my hash array, but can't seem to access the values of it. How can I just get the value of this object?
{"_method"=>"delete", "authenticity_token"=>"Z6ZqriiuXu6ODDqhGgocGiaN12rjKD6pUB6n/2v+CABZDAjwLzwczsMM3nM8f0PI0nww43o5mlC35HK+9PVa8w==",
"domain_name"=>"test.testmodule2.com.",
"hosted_zone_id"=>"/hostedzone/XXXXXXXXXX",
"ttl"=>"3600",
"type"=>"A",
"value"=>[{"value"=>"1.1.1.1"}],
"id"=>"/hostedzone/XXXXXXXXXX"}
def record_params
params.permit!([:hosted_zone_id, :domain_name, :type, :ttl, :alias, :value]).to_h!
end
def destroy
value = params[:value]
# returns [<ActionController::Parameters {"value"=>"1.1.1.1"} permitted: true>]
# would like it to return [{"value"=>"1.1.1.1"}]
end
If that hash is the value of params[:value], then access the value key inside, like:
params[:value] = {
"_method"=>"delete",
"authenticity_token"=>"...",
"domain_name"=>"test.testmodule2.com.",
"hosted_zone_id"=>"/hostedzone/XXXXXXXXXX",
"ttl"=>"3600",
"type"=>"A",
"value"=>[{"value"=>"1.1.1.1"}],
"id"=>"/hostedzone/XXXXXXXXXX"
}
params['value']['value'][0]['value']
# => "1.1.1.1"
params['value']['value'][0].keys
# => ["value"]
I have this:
def some_params
params.require(:person).permit(:name, :pass)
These params are under the key "person" in "params". How can I add a key from the top level of "params" to the list of permitted params? In total it should result into 3 keys of permitted params.
Just add other call to the method require like:
params = ActionController::Parameters.new({
key1: 1,
person: {
name: 'Francesco',
pass: 'pass'
}
})
params.permit(:key1, {:person => [:name, :pass]})
Check the docs at: https://github.com/rails/strong_parameters#require-multiple-parameters
Require Multiple Parameters
If you want to make sure that multiple keys are present in a params
hash, you can call the method twice:
params.require(:token)
params.require(:post).permit(:title)
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.
I want to mass update attributes of an entity.
How can I sanitize properly the params which is coming from grape?
This is my console log about the parameters:
params.except(:route_info, :token, :id)
=> {"display_number"=>"7"}
[18] pry(#<Grape::Endpoint>)> params.permit(:display_number)
ArgumentError: wrong number of arguments (2 for 0..1)
from /Users/boti/.rvm/gems/ruby-2.0.0-p353#thelocker/gems/hashie-2.0.5/lib/hashie/mash.rb:207:in `default'
[19] pry(#<Grape::Endpoint>)> params.sanitize
=> nil
In grape you need to declare your params before the actual method.
Within the method the params object is a Hashie::Mash instance, and does not have APIs like permit and sanitize...
Here is the relevant documentation for declaring and validating parameters in grape:
You can define validations and coercion options for your parameters
using a params block.
params do
requires :id, type: Integer
optional :text, type: String, regexp: /^[a-z]+$/
group :media do
requires :url
end
optional :audio do
requires :format, type: Symbol, values: [:mp3, :wav, :aac, :ogg], default: :mp3
end
mutually_exclusive :media, :audio
end
put ':id' do
# params[:id] is an Integer
end
When a type is specified an implicit validation is done after the
coercion to ensure the output type is the one declared.
If you still want to use strong parameters, you'll need to use the strong_parameters gem, and create a new instance of ActionController::Paramter yourself:
raw_parameters = { :email => "john#example.com", :name => "John", :admin => true }
parameters = ActionController::Parameters.new(raw_parameters)
user = User.create(parameters.permit(:name, :email))
I have a hash in Ruby:
params={"username"=>"test"}
I want to add another associative array like:
params["user"]={"name"=>"test2"}
so params should become
params={"username"=>"test","user"=>{"name"=>"test2"}}
but when I post this params to a url, I get:
params[:user][:name] # => nil
when I dump the user data:
params[:user] # => ['name','test2']
what I want is
params[:user] # => output {'name'=>'test2'}
what am I doing wrong? thanks for help.
You're just using wrong key, you think that :user and "user" are the same, which is not.
params["user"]["name"] #=> "test2"
params["user"] #=> {"name"=>"test2"}
UPDATE from Naveed:
:user is an instance of Symbol class while "user" is instance of String
You have created a hash with keys of type string and trying to access with symbol keys. This works only with class HashWithIndifferentAccess.
If you want to achieve the same convert your hash to HashWithIndifferentAccess by using with_indifferent_access method,
> params = {"username"=>"test", "user"=>{"name"=>"test2"}}
=> {"username"=>"test", "user"=>{"name"=>"test2"}}
> params[:user][:name]
=> nil
>params = params.with_indifferent_access
> params[:user][:name]
=> "test2"
Update: request params is an instance of HashWithIndifferentAccess
The following should work:
params["user"]
params={"username"=>"test"}# params is not array nor associative array its a hash
you can add key value pair in hash by
params["key"]="value"
key and value both can be object of any class,be sure you use same object as key to access value or take a look at
HashWithIndifferentAccess
now
params["user"]={"name"=>"blah"}
params["user"] # => {"name"=>"blah"}
params["user"]["name"] # => "blah"