How can I access an array inside a hash? - ruby-on-rails

I have a hash within an array:
values = {}
values.merge!(name => {
"requested_amount" => #specific_last_pending_quota.requested_amount,
"granted" => #specific_last_pending_quota.granted,
"pending_final" => pending_final
})
#o_requests[request.receiving_organization][request.program_date][:data] = values
I send it to the view and then when I get it so:
= quota[:data].inspect
# {"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}
I want to fetch the object like this:
= quota[:data]["theme"].inspect
But I got this error
can't convert String into Integer

I guess quota[:data] may return array of hash
Try:
= quota[:data][0]["theme"]
Here I tried case to get same error and check:
> h[:data]
#=> [{"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}]
> h[:data]["theme"]
TypeError: no implicit conversion of String into Integer
from (irb):10:in `[]'
from (irb):10
from /home/ggami/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
> h[:data][0]["theme"]
#=> {"requested_amount"=>2, "granted"=>false, "pending_final"=>0}

Try convert it to proper hash I guess it should work fine.
values = {}
values.merge!(name => {:requested_amount => #specific_last_pending_quota.requested_amount, :granted => #specific_last_pending_quota.granted, :pending_final => pending_final})
#o_requests[request.receiving_organization][request.program_date][:data] = values

Related

Rails - good way to convert string to array if not array rails

I receive a param and want it to be either a string like this :
"abc,efg"
or an Array like this
["abc","efg"]
In the first case I want to convert it into an Array, what would be the good way ?
Here is what I thought
if params[:ids] && params[:ids].is_a? Array
ids = params[:ids]
else if params[:ids]
ids = params[:ids].split(",")
I'd use a ternary for this to keep it simple and on one line:
ids = params[:ids].is_a?(String) ? params[:ids].split(',') : params[:ids]
I've reversed the order so you don't get an undefined method error if you try calling split on nil should params[:ids] be missing.
Array.wrap(params[:ids]).map{|x| x.split(',')}.flatten
Apologies for piling on. But I thought I would offer a slight tweak to the answer proposed by SickLickWill (which doesn't quite handle the Array case correctly):
ids = params[:id].split(',').flatten
This will handle the String case just fine:
:001 > params = {id: "abc,efg"}
:002 > ids = params[:id].split(',').flatten
=> ["abc", "efg"]
As well as the Array case:
:003 > params = {id: ["abc","efg"]}
:004 > ids = params[:id].split(',').flatten
=> ["abc", "efg"]
If there's any chance the id param will be nil, then this barfs:
:005 > params = {}
=> {}
:006 > ids = params[:id].split(',').flatten
NoMethodError: undefined method `split' for nil:NilClass
So, you could put in a conditional test:
:007 > ids = params[:id].split(',').flatten if params[:id]
=> nil
Or, use try:
:008 > ids = params[:id].try(:split, ',').try(:flatten)
=> nil
You miss end tag and you have wrong else if and you can delete the check of params[:ids] because if :ids key do not exist is_a? return NilClass
I think you can do this
ids = if params[:ids].is_a? Array
params[:ids]
elsif params[:ids]
params[:ids].split(",")
end
I think the shortest way would be to use .try. It saves you from writing out an if-then-else.
params_id = params[:id].try(:split, ',')

Extract values from a string in Ruby

How to get a value from a string e.g
search_params[:price] = "1460,4500"
How can I get the first number into one variable and second into a different variable?
Did you mean this??:
first_price, second_price = search_params[:price].split(',')
You can use split method
irb(main):002:0> price = "1460,4500"
=> "1460,4500"
irb(main):003:0> price.split(',')
=> ["1460", "4500"]
irb(main):004:0> a, b = price.split(',')
=> ["1460", "4500"]
irb(main):005:0> a
=> "1460"
irb(main):006:0> b
=> "4500"

Can't save mongoid hash value

I have a mongoid object
#tran = Translations.where({:_id => params[:id]})[0]
The object #tran has a array of hashes at #tran[:translations]
I tried changing the value of a hash in the array like so:
#tran[:translations][0]['rated'] = (#tran[:translations][0]['rated']+1)
and I did a #tran.save
But the value does not seem to be updated.
What am I doing wrong here?
PS, Here's the value of #tran[:translations] : [{"value":"hello3","rating":100,"rated":0}]
#tran = Translation.find params[:id]
You can use this line ->
#tran.update_attributes(:rated => #tran.rated+1)
Or this line ->
#tran.rated += 1
#tran.save

`try` method when trying to fetch hash value

I'm trying to avoid an error message when pulling from a hash which may or may not have a value. I either want it to return the value or return nil.
I thought the try method would do it, but I'm still getting an error.
key not found: "en"
My hash is an hstore column called content... content['en'], etc.
content = {"es"=>"This is an amazing event!!!!!", "pl"=>"Gonna be crap!"}
Try method
#object.content.try(:fetch, 'en') # should return nil, but errors even with try method
I thought this would work but it doesn't. How else can I return a nil instead of an error?
Also, the content field itself might also be nil so calling content['en'] throws:
undefined method `content' for nil:NilClass
If you need to allow for object.content.nil?, then you'd use try. If you want to allow for a missing key then you don't want fetch (as Priti notes), you want the normal [] method. Combining the two yields:
object.content.try(:[], 'en')
Observe:
> h = { :a => :b }
=> {:a=>:b}
> h.try(:[], :a)
=> :b
> h.try(:[], :c)
=> nil
> h = nil
=> nil
> h.try(:[], :a)
=> nil
You could also use object.content.try(:fetch, 'en', nil) if :[] looks like it is mocking you.
See the Hash#fetch
Returns a value from the hash for the given key. If the key can’t be found, there are several options: With no other arguments, it will raise an KeyError exception; if default is given, then that will be returned; if the optional code block is specified, then that will be run and its result returned.
h = { "a" => 100, "b" => 200 }
h.fetch("z")
# ~> -:17:in `fetch': key not found: "z" (KeyError)
So use:
h = { "a" => 100, "b" => 200 }
h.fetch("z",nil)
# => nil
h.fetch("a",nil)
# => 100
Just use normal indexing:
content['en'] #=> nil
As of Ruby 2.0, using try on a possibly nil hash is not neat. You can use NilClass#to_h. And for returning nil when there is no key, that is exactly what [] is for, as opposed to what fetch is for.
#object.content.to_h["en"]

Get value from a Rails nested hash

I have a Rails nested hash as follow:
class = [{"tutor" => {"id" => "Me"}}, {"tutor" => {}}]
I would like to extract id list, but the nested hash can be nil:
tutor_ids = class.map {|c| c['tutor']['id'].to_i }
In case the nested hash is nil, I'll get error.
How do I go about this?
First of all I think you were probably thinking of an array of hashes like so (given the same key was used multiple times:
klass = [{"tutor" => {"id" => "Me"}},{"tutor" => {}}]
Then you could map the tutor IDs with:
tutor_ids = klass.map {|k| k['tutor'] && k['tutor']['id'] }.compact
which would result in
=> ["Me"]
Compact will throw out all the nil values encountered afterwards.
id = class['tutor'] ? class['tutor']['id'] : nil

Resources