How to accept hash parameters - ruby-on-rails

Here are the parameters being passed:
{"utf8"=>"✓",
"authenticity_token"=>"j3R0aro/Arg4Y3Zu6zIIxZYbYTxqoqyKEGc11CkvYDU=",
"inventory"=>{
"9"=>"0",
"12"=>"0",
"1"=>"0",
"2"=>"0",
"3"=>"0",
"10"=>"0",
"11"=>"0",
...
}
}
I can't seem to grab the params in inventory, for whatever reason, the code below keeps wanting to grab the inventory as one long array of hashes rather than the hashes themselves. What am I doing wrong?
def inventory_params
params.permit(inventory: [{:itemlist_id => :quantity}] )
#inventory_params = params.reject { |k, v| (v == "") || ( v == "0" ) }
end
I also tried params.permit(inventory: {:itemlist_id => :quantity} ) which didn't work either

params.require(:model_name).permit(:inventory)
will work I guess.

What ended up working:
params["inventory"]

Related

removing a value from hash if key matches rails

I have seen many answers as removing any key which has value of nil or "", But this is not what i want.
I have a hash like this
{"firstname"=>"Jie",
"lastname"=>"Pton",
"email"=>"jami4#yahoo.com",
"country_id"=>"1",
"payment_method"=>"0",
"insight_id"=>"",
"password"=>""}
And I only want to remove the password attribute from hash if its empty, NOT ALL which are empty
More generic solution: for the hash given as an input (I assume it’s params, so let’s call it params) and the list of fields to be removed when empty:
TO_REMOVE_EMPTY = %w|password|
params.delete_if { |k, v| TO_REMOVE_EMPTY.include?(k) && v.empty? }
hash.delete('password') if hash['password'].blank?
You can also use this solution:
hash.reject { |k,v| v.nil? || v.empty? }
You can use:
hash.reject{|k,v| k == 'password' && (v.nil? || v.empty?)}
or if you want to remove "password" key from original hash you can use "!"
eg. hash.reject!{|k,v| k == 'password' && (v.nil? || v.empty?)}

Database driven radio button ruby on rails

I am trying to update my conditions table with the radio button's value on and off
Here is the view
= form_tag('/admin/save',:action => 'update') do
= radio_button_tag("#{cols}_#{id}",1,checked = eval(check), options = {})
= radio_button_tag("#{cols}_#{id}",0,checked = eval(negcheck), options = {})
= submit_tag
Here is the controller
def updateCondition
params.each do |keys , value|
key ="#{keys}"
condition = key.split("_")[0]
hospitalid =key.split("_")[1]
if condition == "utf8" || condition == "authenticity" || condition == "commit"
next
end
Condition.find(hospitalid).update(:"#{condition}" => params["#{condition}_#{hospitalid}"])
end
render nothing: true
end
Params are :
{"utf8"=>"✓",
"authenticity_token"=>"",
"abc_10000"=>"1",
"commit"=>"Save changes",
"def_10000"=>"1",
}
Here is my question :
1) Why params is not showing all my radio button values ?
2) Any way to handle utf8, authentication_token, commit other than if statement ?
This may be why params not showing:
This looks strange to me: checked = eval(check) should it be checked: eval(check) or checked == eval(check)
Why are you setting options = {}? I think options should be passed in as a hash or not passed in at all.
Regarding #2,
if condition == "utf8" || condition == "authenticity" || condition == "commit"
next
end
Condition.find(hospitalid).update(:"#{condition}" => params["#{condition}_#{hospitalid}"])
You could extract that into a separate function:
def condition_valid?
condition == "utf8" || condition == "authenticity" || condition == "commit"
end
You're asking two questions here which is bad protocol for SO. I'll answer the second one.
Rather than try to filter out the parameters you don't want, which is very fragile, you could send through all the things you are trying to process, grouped into a single param. Eg, in your form, change the radio buttons to
= form_tag('/admin/save',:action => 'update') do
= radio_button_tag("conditions[#{id}][#{cols}]"}",1,checked = eval(check), options = {})
= radio_button_tag("conditions[#{id}][#{cols}]"}",0,checked = eval(negcheck), options = {})
= submit_tag
this will give you params like
{"utf8"=>"✓",
"authenticity_token"=>"",
:conditions => {1000 => {:abc => 1, :def => 1}},
"commit"=>"Save changes"
}
See how they are organised and separated? This means you don't have to muck about splitting them up again.
Now your controller code could be:
def updateCondition
params[:conditions].each do |id , attributes|
if condition = Condition.find_by_id(id)
condition.update_attributes(attributes)
end
end
render nothing: true
end
Note: you don't say what the value of "cols" is when you are building the form so i'm having to guess a bit. I think i just copied the way you are using it but shuffled it around a bit. There is almost certainly a cleaner way to build the form too.

How to take keys within hash objects

hash = {
"d" => {
"o" => {
"g" => {
"s" => {}
},
"l" => {
"l" => {}
},
"o" => {
"m" => {}
}
}
},
"b" => {
"o"=>{
"o"=>{
"m"=>{}
}
}
}
}
trie.print(hash)
Within the Trie class there is method called print to print trie:
def print(trie)
trie.each do |k,v|
#res.concat(k)
print(trie[k]) if trie[k].length > 0
unless trie[k].length > 0
#result << #res unless trie[k].length > 0
#res = ""
p #result
end
end
end
The above method prints:
["dogs", "ll", "om", "boom"]
But I want to print:
["dogs" , "doll", "doom" , "boom"]
I think we don't have to pass the prefix.
def compose(trie)
trie.flat_map do |k, v|
v.empty? ? k : compose(v).map{|sv| "#{k}#{sv}"}
end
end
I've renamed the function to compose to avoid clashing with Kernel#print. The reason for that is that I'm calling this function from the inside, where it should be callable without pointing to an object explicitly. The approach you're using doesn't "reuse" traversed prefixes. The most common way to do this is to use recursion and build up that prefix in the arguments.
I've got this recursive function. Recursion is a common approach to processing trees. It accepts a "subtrie" and a prefix it's placed below (defaults to empty string, if none given). Recursion base: if we got an empty subtrie, we return a single-element array of a built up prefix at this point. Higher levels will return arrays of prefixes built from a given "subtrie".
def compose(trie, prefix="")
trie.flat_map do |k, v|
new_prefix = prefix + k
results = compose(v, new_prefix)
results.empty? ? new_prefix : results
end
end
Note flat_map, otherwise (with map) it will output a deeply nested array structured as your trie with leaves replaced with built up prefixes.
UPD: the new version returns an empty array for empty subtrie.

Rails strong parameters of enumerated type

I've got paramerers which are sent by a form like:
{ "mac"=>{"0"=>["111", "222"], "1"=>["333", "444"]} }
How can I permit them in a proper way, because I've found just an ugly solution:
params.permit(mac: Hash[(0..100).map { |i| [i.to_s, []] }])
Fetch the keys out of the :mac key and then permit them.
mac_keys = params.fetch(:mac, {}).keys
params.permit(mac: mac_keys)
will you consider the hash's keep_if method, as params is just a hash.
params[:mac].keep_if {|k, v| k.to_i >= 0 and k.to_i <= 100}

Hashes in hashes ruby on rails

I'm passing the below information through parameter from view to controller
parameters:{"Something"=>{"a" => "1", "b" => "0", "c" => "1", "d" => "0" #and so on}}
I want to access all the characters that have "1" as their value and concatenate into the string.
I tried
Something.each do |key, value|
if(value == "1")
string = string + key
end
end
It is throwing error saying that it could not execute nil.each and that i might be expecting an array.
It appears to me that Something is a hash and in turn has some hashes in it.
So i initialised Something to
Something = Hash.new { |Something, k| Something[k] = Hash.new }
But i still get the same error.
Just work with the params hash. This should do what you need:
params["Something"].select {|k, v| v == "1"}.keys.reduce(:+)
select filters the params to only those with the value "1"
keys returns an array with all the keys in the hash
reduce joins all elements with a concat operation (+)
Edit
To concatenate and add the "Extra" word:
For each parameter:
params["Something"].select {|k, v| v == "1"}.keys.inject("") {|result, p| result += "Extra #{p}"}
Only to the extra parameters, but not to the first one:
params["Something"].select {|k, v| v == "1"}.keys.inject {|result, p| result += "Extra #{p}"}
See more information on inject here.

Resources