Ruby to_s isn't converting integer to string - ruby-on-rails

I'm trying to convert some values in a hash into a string but the type stays the same.
recommended_stores = []
results['data'].each do |stores_list|
stores_list['stores'].each do |store|
store['id'].to_s
end
recommended_stores << stores_list['stores']
end
Am I missing something here?

the method #to_s just returns the element converted to a string, but does not actually convert the element to a string permanently. instead of using #each, you could use #map, like this.
results['data'].map do |stores_list|
stores_list['stores'].each do |store|
store['id'] = store['id'].to_s
end
end
That would return an array of arrays, if you want it to be just one array you can use #flat_map.

you got everything but you are not storing it, i think assigning the value of hash with the value.to_s would work, can you try as below
recommended_store = []
results['data'].each do |stores_list|
stores_list['stores'].each do |store|
store['id'] = store['id'].to_s
end
recommended_store << stores_list['stores']
end
Note : in your question array declared is "recommended_store" and last line you are pushing elements in to "recommended_stores" hope its just a typo, and not the cause of problem :-)

Related

Converting array with .join not saving value

I have a method do_stuff that takes a string as a value. However, an array of two strings is occasionally passed in. In this situation, I need to convert the array to a single string (without commas). So for example, ["hello", "world"] should become "hello world".
So, if value = array, join the two strings, otherwise leave it alone.
The following line I have does what I want, but I am struggling with actually "saving" the value before passing it to the method do_other_stuff.
def do_stuff(value)
value.join("") if value.is_a? Array
do_other_stuff(value)
end
So I think i am close, but what would be the best way to ensure value is manipulated before passing it to do_other_stuff ?
join does not change your object, you're wasting its return value
value = value.join if value.is_a? Array
Note that "" is the default for the join parameter, so I got rid of it
Replace
value.join("") if value.is_a? Array
With
value = value.join("") if value.is_a? Array
Basically you need to reassign result back to value
Use duck typing instead of checking the class:
def do_stuff(value)
do_other_stuff(value.try(:join, '') || value)
end
.try is from ActiveSupport and will return nil if the object does not respond to the method. In plain old ruby you would write this as:
def do_stuff(value)
do_other_stuff(value.respond_to?(:join) ? value.join("") : value)
end

How can i replace a parameter by looping parameters in ruby?

I have an array of parameters and i want to replace all parameters by looping over array in ruby on rails.
I am using before_action in controller as
before_action :cost_format
This is an array of parameters. The format of the parameter is string, i want to run a function on each parameter and convert it into float. So i am looping an array and calling function on each element.
def cost_format
x = [params[:cost_1], params[:cost_2], params[:cost_3]]
x.each do |i|
convert_cost(i)
end
end
I have a function convert_cost as following
def convert_cost(x)
x.gsub(',', '.').to_f
end
How do i loop an array so that my parameters get replaced.? Parameters are not being replaced by above code. Any hint would be appreciated.
Thanks
I think you'll want something like this:
def cost_format
%i(cost_1 cost_2 cost_3).each do |key|
params[key] = convert_cost(params[key])
end
end
def convert_cost(val)
val.gsub(',', '.').to_f
end
This grabs each key from your params and replaces the value with it passed through the convert_cost method.
Edit: you might be able to ignore this section about convert_cost due if it works with the format you're getting your numbers in. Please excuse my ethnocentrism :)
I've not updated your convert_cost method, though I'm a little wary about whether it will work at the moment. If you've got, for example "1,234,567" and you call your gsub you get "1.234.567". Calling to_f on that gives you 1.234, which I wouldn't think you'd want?
Instead of that, you could use:
def convert_cost(val)
val.gsub(',', '').to_f
end
E.G.
convert_cost("1,234,567")
# => 1234567.0
Combining all that, the following would be converted like so:
params = { cost_1: "1,234,567", cost_2: "123", cost_3: "456.5", cost_4: "I won't be touched" }
# after `cost_format` before_action runs:
# => {:cost_1=>1234567.0, :cost_2=>123.0, :cost_3=>456.5, :cost_4=>"I won't be touched"}
Let me know how you get on or if you have any question - hope this helps.
Could you try something like
x.map{|param| param.gsub(',', '.').to_f}
directly on your array.
So your cost_format method will look like:
def cost_format
x = [params[:cost_1], params[:cost_2], params[:cost_3]]
result = x.map{|param| param.gsub(',', '.').to_f}
# do stuff with result
end
I think the reason it's not working because, each method returns its receiver, but map returns a new array.

JSON no implicit conversion of String into Integer in Ruby

I'm grabbing a JSON hash from my server and trying to read it in my ruby script. It seems to be returning the wrong value though, unless I'm just loosing my mind:
I'm calling this from a function:
def get_functions(serial_number)
response = HTTParty.get("#{get_host_url}/v1/devices/#{serial_number}.json")
data = response['scan_option']
return data
end
Here is the returned JSON:
{"can_scan"=>true, "can_brute_ssh"=>false, "can_brute_telnet"=>false, "can_brute_voip"=>false, "can_brute_smtp"=>false, "can_brute_pop3"=>false, "can_google_crawl"=>false, "can_scan_external_ip"=>false, "scan_ip_list"=>["10.10.10.1"], "exclude_ip_list"=>[]}
Which is then read into the following code:
data.each do |d|
#can_scan = d['can_scan']
# ....
end
However this is throwing an error:
no implicit conversion of String into Integer
{foo: :bar}.each do |d|
p d
d['meow']
end
# => [:foo, :bar]
#! TypeError: no implicit conversion of String into Integer
Hash#each yields a two element array ([key, value]). You then try to index that array with d["can_scan"], which fails as arrays can only be indexed with integers.
Instead, directly access the value - data['can_scan'].
I you mean that data in your third snippet (where you call data.each) is the hash mentioned just above it, indeed that would be troublesome. Calling each on a hash will itterate over its key, value pairs, giving you an array in the block var d of the data.each (with a [key, value] pair in it).
You might just want to call data['can_scan'].
Note that the return at the end of your method defenition is not needed in Ruby. You can just do:
def get_functions(serial_number)
response = HTTParty.get("#{get_host_url}/v1/devices/#{serial_number}.json")
response["scan_option"]
end

no implicit conversion of Symbol into Integer, rails 4

I have been getting this error, no implicit conversion of Symbol into Integer. I searched for this error but don't really understand it. Code is at the bottom. Once it gets to this "if q[:text_field].is? Array" that is when it gives the error and I'm sure that the rest of that code is wrong. But no idea how to fix it.
pages = Vovici::API.new(#pid).survey_structure
This is a sample of the api data that I'm calling with the code above.
[{:q_fill_in=>
{:heading=>{:text=>"1"},
:instructions=>{:text=>nil},
:body=>{:text=>"Pac"},
:list_caption=>{:text=>{:#type=>"plain"}},
:total_label=>{:text=>"Total"},
:text_field=>
[{:label=>{:text=>"first"},
:preselection=>{:text=>{:#type=>"plain"}},
:symbol=>{:text=>{:#type=>"plain"}},
:#id=>"1",
:#dbheading=>"Q1_1",
:#row=>"0",
:#size=>"20",
:#xmltype=>"text",
:#required=>"false",
:#compare_expression=>"-1",
:#topic_first=>"true",
:#slider=>"false",
:#sliderstep=>"1",
:#published=>"true",
:#usecalendarpopup=>"true",
:#insert_symbol_left=>"false",
:#label_width=>"3",
:#text_area_width=>"9"},
{:label=>{:text=>"id"},
:preselection=>{:text=>{:#type=>"plain"}},
:symbol=>{:text=>{:#type=>"plain"}},
:#id=>"2",
:#dbheading=>"Q1_2",
:#row=>"0",
:#size=>"20",
:#xmltype=>"text",
:#required=>"false",
:#compare_expression=>"-1",
:#topic_first=>"true",
:#slider=>"false",
:#sliderstep=>"1",
:#published=>"true",
:#usecalendarpopup=>"true",
:#insert_symbol_left=>"false",
:#label_width=>"3",
:#text_area_width=>"9"}],
:#dbheading=>"Q1"}
This is code from my rb file
def process
pages = Vovici::API.new(#pid).survey_structure
pages.each do |page|
if page[:q_fill_in]
process_fill_in(*page[:q_fill_in])
end
end
end
def process_fill_in(*questions)
questions.each do |q|
if q[:text_field].is? Array
sub_qs = q[:text_field]
else
sub_qs = [q[:text_field]]
end
q_text = clean_question_text(q[:body][:text])
sub_qs.each do |sq|
sub_text = clean_question_text(sq[:label][:text])
q_name = [q_text, sub_text.reject { |i| i.nil? || i.empty? }.join("--")]
#survey.questions.create!(qheader: sq[:#dbheading], qtext: q_name)
end
end
end
def clean_question_text(text)
match = /( )?(<.*?>)?(.+)( )?(<\/.*>)?/.match(text)
match[3]
end
Can anyone please help?
This error means that you've used [] on an array but you've passed something that doesn't make sense to an array. In this particular case it's telling you that q which you are trying to use as a hash is in fact an array.
This is happening because process_fill_in(*page[:q_fill_in]) is turning the hash into an array of key-value pairs (because of the *). I'm not sure why you've got a splat there at all.

Rails syntax error assigning a variable with each loop

I'm trying to create a list of recipients to send in an external request by assigning it to a variable by doing the following:
recipients = #items.each do |item|
{"email"=>"#{Recipient.find_by_id(item.recip_id).email}", "amount"=>"#{item.price}"},
end
but I'm getting this error:
syntax error, unexpected ',', expecting '}'
I know that what I've done is not the right syntax. I'm kind of a Ruby newbie, so can someone help me figure out the correct syntax here?
EDIT: Thanks for the input. But what if I need to do two hashes for each item?
recipients = #items.map do |item|
{"email"=>"#{Recipient.find_by_id(item.recip_id).email}", "amount"=>"#{item.price}"},
{"email"=>"#{Store.find_by_id(item.recip_id).email}", "amount"=>"#{item.price}"}
end
The problem is with the comma at the end of the hash. Also if you want to store the email and amount in recipients, you should use map. This will return an array of hash with email and amount:
recipients = #items.map do |item|
{"email"=> Recipient.find_by_id(item.recip_id).email, "amount"=> item.price}
end
Also, as you might note, I don't need to pass the values of email and prices as a string.
If you want to return multiple hashes from your map block then you'd be better off switching to each_with_object:
Iterates the given block for each element with an arbitrary object given, and returns the initially given object.
So something like this:
recipients = #items.each_with_object([]) do |item, a|
a << {"email"=>"#{Recipient.find_by_id(item.recip_id).email}", "amount"=>"#{item.price}"}
a << {"email"=>"#{Store.find_by_id(item.recip_id).email}", "amount"=>"#{item.price}"}
end

Resources