Delete a hash from array of hashes in rails [duplicate] - ruby-on-rails

This question already has answers here:
Deleting a hash from array of hashes in Ruby
(2 answers)
Closed 5 years ago.
I have array of hashes in json format, and I have to remove one of the hash from that array, I am iterating that array and if that particular key/ value matches i am deleting that hash,
I found clear() method but, clear leaves the {}, which I don't require
I want the whole hash to be removed
[{"question":"0a2a3452","answer":"lopq"},
{"question":"58deacf9","answer":"admirationo"},
{"question":"32c53e","answer":"acion"},
{"question":"b5546bcf","answer":"figure"},
{"question":"4f246a10","answer":"zelta"},
{"question":"bf546c04","answer":"deltaa"}]
i.e if my key matches as "0a2a3452", I want to delete the first hash

You can do with delete_if method:
arr = [{"question":"0a2a3452","answer":"lopq"},
{"question":"58deacf9","answer":"admirationo"},
{"question":"32c53e","answer":"acion"},
{"question":"b5546bcf","answer":"figure"},
{"question":"4f246a10","answer":"zelta"},
{"question":"bf546c04","answer":"deltaa"}]
arr.delete_if {|a| a[:question] == '0a2a3452' }

Try this:
items = [
{"question":"0a2a3452","answer":"lopq"},
{"question":"58deacf9","answer":"admirationo"},
{"question":"32c53e","answer":"acion"},
{"question":"b5546bcf","answer":"figure"},
{"question":"4f246a10","answer":"zelta"},
{"question":"bf546c04","answer":"deltaa"}
]
items = items.reject {|i| i[:question] == '0a2a3452'}

Related

Rails, how to loop either array of hashes or only a hash

I am connecting to an API and I get array of hashes or only 1 hash for the data. So when the data comes as array of hashes;
"extras"=>{"extra"=>[{"id"=>"529216700000100800", "name"=>"Transfer Trogir - Dubrovnik (8 persons max)", "price"=>"290.0", "currency"=>"EUR", "timeunit"=>"0", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2119-07-20", "sailingdatefrom"=>"1970-01-01", "sailingdateto"=>"2119-07-20", "obligatory"=>"0", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}, {"id"=>"528978430000100800", "name"=>"Gennaker + extra deposit (HR)", "price"=>"150.0", "currency"=>"EUR", "timeunit"=>"604800000", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2119-07-19", "sailingdatefrom"=>"1970-01-01", "sailingdateto"=>"2119-07-19", "obligatory"=>"0", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}]
I'am looping through the array to get the values as;
b["extras"]["extra"].each do |extra|
puts extra["id"]
puts extra["name"]
end
But when this is not array; only 1 hash, then this is not working, adding each loop makes it array but not array of hashes;
"extras"=>{"extra"=>{"id"=>"640079840000100800", "name"=>"Comfort package (GRE)", "price"=>"235.0", "currency"=>"EUR", "timeunit"=>"0", "customquantity"=>"0", "validdatefrom"=>"1970-01-01", "validdateto"=>"2120-03-25", "sailingdatefrom"=>"2015-01-01", "sailingdateto"=>"2120-03-25", "obligatory"=>"1", "perperson"=>"0", "includedinbaseprice"=>"0", "payableoninvoice"=>"1", "availableinbase"=>"-1", "includesdepositwaiver"=>"0", "includedoptions"=>""}}
b["extras"]["extra"].each do |extra|
puts extra["id"]
puts extra["name"]
end
This time, that gives error TypeError (no implicit conversion of String into Integer);
When I type puts extra.inspect; I get ["id", "640079840000100800"]. So to make it work I should pass extra[1] to get the id number.
But I can not predict either array of hashes or only hash. Is there any easy way to solve this issue that works either array of hashes or just a hash?
Naïve solution: one might check the object’s type upfront:
case b["extras"]["extra"]
when Array
# handle array
when Hash
# handle hash
end
Proper solution: produce an array of hashes no matter what came.
[*[input]].flatten
and deal with it as with an array having at least one hash element (with each.)
Please also refer to valuable comment by #Stefan below if you have no allergy using Rails helpers.
You could try to use Object#kind_of? to determine whether it is an Array or a Hash instance.
if b["extras"]["extra"].kind_of? Array
# handle array
elsif b["extras"]["extra"].kind_of? Hash
# handle hash
end

Rails: set params but do not save [duplicate]

This question already has answers here:
Rails update_attributes without save?
(4 answers)
Closed 6 years ago.
What's the call to update a Rails record with new params, say, stored in a hash variable? This:
#user.update(hash)
Will save the record, and since I want to put the call in a callback I don't want to save it, just prepare it to be saved correctly in the callback.
You can use attributes= to set the attributes but not save the record.
#user.attributes = hash
New attributes will be persisted in the database when the object is saved. See http://apidock.com/rails/ActiveRecord/AttributeAssignment/attributes
You can do:
#user.attributes = hash
or
#user.assign_attributes hash
Keep in mind that neither of these will return the object you're working on. If you want that, try Object#tap:
#user.tap { |u| u.assign_attributes hash }

Use params value with variable in ruby on rails? [duplicate]

This question already has an answer here:
Use variable in parameter ruby on rails? [closed]
(1 answer)
Closed 7 years ago.
I want to check if param key exists with a variable name and if it exists I want to use value something like params[filenamestring[-1]].
filenamestring is any array generate with split
If you variable is a hash than here is your answer
if params.has_key?(filenamestring[-1])
param_value = param[filenamestring[-1]]
end
You can check existence of key using has_key? method:
key = filenamestring[-1]
# or, key = filenamestring.last
if params.has_key?(key)
value = params[key]
# do stuff with value
end

Elegantly handling blank values in a nested hash [duplicate]

This question already has answers here:
How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?
(16 answers)
Closed 7 years ago.
I'm sure I've seen an elegant solution to this before, but I can't quite find it:
I have a rails controller which may-or-may-not have the following hash element:
myhash[:parent_field]
Inside that parent field, a child element could also be blank. I'm currently checking that via the (very ugly) method:
if (!myhash[:parent_field] || !myhash[:parent_field][:child_field] || myhash[:parent_field][:child_field].blank?)
Which works, but I figure - surely - there has to be a more elegant way. Just to reiterate:
myhash[:parent_field] may or may not exist
If it does exist, myhash[:parent_field][:child_field] may or may not exist
If that exists, it may or may not be blank.
#fetch is your friend:
my_hash.fetch(:parent, {})[:child].blank?
What I would do is just use local variables to ease your burden:
unless (p=foo[:parent]) && (c=p[:child]) && !c.blank?
# Stuff is borked!
end
But let's explore alternatives, for fun…
If you can't change your data structure (that's a Hash, by the way, not an Array) then you can use the Ruby andand gem in conjunction with the Rails' try as lazy ways of calling methods on things that might be nil objects.
You could alternatively change your data structure to Hashes that return empty auto-vivifying hashes when you ask for a key that does not exist:
mine = Hash.new{ |h,k| Hash.new(&h.default_proc) }
mine[:root] = { dive:42 }
p mine[:root][:dive] #=> 42
p mine[:ohno][:blah][:whee] #=> {}
p mine[:root][:blah][:whee] #=> undefined method `[]' for nil:NilClass (NoMethodError)
However, you'd have to ensure that every object in your hierarchy was one of these hashes (which I explicitly failed to do for the contents of :dive, resulting in the error).
For alternative fun, you could add your own magic lookup method:
class Hash
def divedive(*keys)
obj = self
keys.each do |key|
return obj unless obj && obj.respond_to?(:[])
obj = obj[key]
end
obj
end
end
if myarray.divedive(:parent,:child).blank?
# ...
This is a frequently asked question and should probably be closed as a duplicate of
Ruby - Access multidimensional hash and avoid access nil object
Is there a clean way to avoid calling a method on nil in a nested params hash?
Ruby: Nils in an IF statement
The first in that list was closed as a dup of the other two, though I believe my answer there has more comprehensive coverage of techniques to address this problem than the later two.
It probably depends on what your actual needs are, but an OOP approach to this would be to convert the arrays and hashes into actual objects. Each object would manage its relationships (similar to ActiveRecord), and would know how to get children and parents.
Since nil.blank? is true, you can remove the middle condition and simplify to this:
if !myarray[:parent_field] || myarray[:parent_field][:child_field].blank?
Also, calling a Hash myarray is a bit misleading.

Ruby element present in array or not [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
how to check if my array includes an object - rails
I have array
array['one', 'two', 'three']
How i find that 'two' element present in array.
Is any method in ruby which can find this?
Thanks
array.include?('two') returns true or false
http://ruby-doc.org/core/classes/Array.html#M002203
array.include?('two')
you can use:
array.index('two')
will return index of object if present else will return nil.

Resources