“can't convert Symbol into Integer” weird error - ruby

The is the hash I am working on,
a = {
#...
:fares => {
:itinerary_fare => {
:segment_names=>"C",
:free_seats => "6",
:fare_for_one_passenger => {
:free_seats=>"0",
:#currency => "TL",
:#non_refundable => "false",
:#price => "439.0",
:#service_fee => "25.0",
:#tax => "33.0",
:#type => "Y"
},
:#currency => "TL",
:#non_refundable => "false",
:#price => "439.0",
:#service_fee => "25.0",
:#tax => "33.0",
:#type => "C"
},
:#currency => "TL",
:#tax => "33.0"
},
#..
}
also here another example http://pastebin.com/ukTu8GaG.
The code that gives me headhaches,
a[:fares][:itinerary_fare].each do |f|
puts f[:#price]
end
If I write this into console, it gives me "can't convert Symbol into Integer" error. But if I write, a[:fares][:itinerary_fare][:#price] it works pretty fine.
The weirdest part is, if I write the code to a haml file
%tbody
-#flights.each do |a|
%tr.flight
%td
-a[:fares][:itinerary_fare].each do |f|
-puts f[:#price] #Weird stuff happens here
.prices
%input{:type=>"radio",:name=>"selectedfight",:value=>"#{a[:id]}"}
= f[:#price]
%br
It works, it prints the prices to my console, yet it fails at the SAME LINE.
can't convert Symbol into Integer file: flights.haml location: [] line: 18
This is the most disturbing error I have ever seen, thanks for any help.
Most of the time there are more than 1 :itinerary_fare, I have to iterate.
My data can be shown as http://postimage.org/image/6nnbk9l35/

a[:fares][:itinerary_fare] is a Hash. Hash#each yields key-value-pair arrays to the block.
So, f takes e.g. the array [:#price, "439.0"] in the block.
Hence you are using a symbol (:#price) as an array index. An integer is expected.
In a[:fares][:itinerary_fare][:#price] you are giving it as hash key which works of course.

Why did you delete the previous question, that was already correctly answered? You could only just updated it with more information.
As was answered by other user in your previous post you are iterating over the elements in a[:fares][:itinerary_fare]. You can see this with:
a[:fares][:itinerary_fare].each do |f|
puts f
end
And you dont need a loop, you can use:
a[:fares][:itinerary_fare][:#price]
If you have more than one :itinerary_fare it will only consider the last one, since it's a key of the hash :fares. Maybe you need an array like (left to minimal of elements):
a = {:id=>"1",
:fares=>{
:itinerary_fares=>[{:#price=>"439"}, {:#price=>"1000"}]
}
}
and then:
a[:fares][:itinerary_fares].each do |f|
puts f[:#price]
end

Related

Why can't my script access classes that are in different directory?

I am trying to access classes DealState and NotAnEndState that are in another directory, where I have a lib called move-to-go.
move-to-go folder contains modules where the one in my example is named deal_state.rb. When i open deal_state.rb it contains the following the code below.
Path to lib: F:\Ruby25-x64\lib\ruby\gems\2.5.0\gems\move-to-go-5.3.0\lib\move-to-go
module MoveToGo
module DealState
# This is the default, a deal with a status with this state is
# currently being worked on.
NotAnEndState = 0
# The deal has reached a positive end state, eg we have won
# the deal.
PositiveEndState = 1
# The deal has reached a negative end state, eg we have lost
# the deal.
NegativeEndState = -1
end
end
Path to my code: C:Users/Shahin/MigrationFolder/converter.rb
class Converter
def configure(rootmodel)
rootmodel.settings.with_organization do |organization|
organization.set_custom_field( { :integration_id => 'source', :title => 'Källa', :type => :Link } )
end
rootmodel.settings.with_person do |person|
person.set_custom_field( { :integration_id => 'source', :title => 'Källa', :type => :String} )
end
rootmodel.settings.with_deal do |deal|
assessment is default DealState::NotAnEndState
deal.add_status( {:label => '1. Kvalificering' })
deal.add_status( {:label => '2. Deal closed', :assessment => MoveToGo::DealState::PositiveEndState })
deal.add_status( {:label => '4. Deal lost', :assessment => MoveToGo::DealState::NegativeEndState })
end
end
When I execute my script I get this error message:
C:Users/MyUserName/MigrationFolder/converter.rb:63:in `block in configure': uninitialized constant Converter::DealState (NameError)
Did you mean? DEAL_SHEET
New things have however come to light. The error message seems to have an issue with the Converter-class, but i cant really interpret what it is implying.
This line is the error : assessment is default DealState::NotAnEndState.
First you should use MoveToGo::DealState::NotAnEndState and second assessment is default should be in a spec file not here.
If you juste remove this line, there should be no error anymore.

ruby object to_s gives unexpected output

What is the correct way to view the output of the puts statements below? My apologies for such a simple question.... Im a little rusty on ruby. github repo
require 'active_support'
require 'active_support/core_ext'
require 'indicators'
my_data = Indicators::Data.new(Securities::Stock.new(:symbol => 'AAPL', :start_date => '2012-08-25', :end_date => '2012-08-30').output)
puts my_data.to_s #expected to see Open,High,Low,Close for AAPL
temp=my_data.calc(:type => :sma, :params => 3)
puts temp.to_s #expected to see an RSI value for each data point from the data above
Maybe check out the awesome_print gem.
It provides the .ai method which can be called on anything.
An example:
my_obj = { a: "b" }
my_obj_as_string = my_obj.ai
puts my_obj_as_string
# ... this will print
# {
# :a => "b"
# }
# except the result is colored.
You can shorten all this into a single step with ap(my_obj).
There's also a way to return objects as HTML. It's the my_obj.ai(html: true) option.
Just use .inspect method instead of .to_s if you want to see internal properties of objects.

Ruby find key by name inside converted JSON array of hashes

I have a Ruby hash converted from JSON data, it looks like this:
{ :query => {
:pages => {
:"743958" => {
:pageid => 743958,
:ns => 0,
:title => "Asterix the Gaul",
:revisions => [ {
:contentformat => "text/x-wiki",
:contentmodel => "wikitext",
:* => "{{Cleanup|date=April 2010}}\n{{Infobox graphic novel\n<!--Wikipedia:WikiProject Comics-->...
All the good stuff is inside the revisions array and then the Infobox hash.
The problem I have is getting to the Infobox hash. I can't seem to get to it. The pages and pageid hashes might not exist for other entries and of course the ID would be different.
I've tried all sorts of methods I could think of like .map, .select, .find, .include?, etc to no avail because they are not recursive and will not go into each key and array.
And all the answers I've seen in StackOverflow are to get the value by name inside a one-dimensional array which doesn't help.
How can I get the Infobox data from this?
Is this what you're looking for?
pp data
=> {:query=> {:pages=>
{:"743958"=>
{:pageid=>743958,
:ns=>0,
:title=>"Asterix the Gaul",
:revisions=>
[{:contentformat=>"text/x-wiki",
:contentmodel=>"wikitext",
:*=>"{{Cleanup..."}]}}}}
# just return data from the first revisionb
data[:query][:pages].map{|page_id,page_hash| page_hash[:revisions].first[:"*"]}
=> ["{{Cleanup..."]
# get data from all revisions
data[:query][:pages].map{|page_id,page_hash| page_hash[:revisions].map{|revision| revision[:"*"] }}.flatten
=> ["{{Cleanup..."]

how non existing hash key returns empty string?

Here is the exact problem;
$ hash
=> {:createAuthenticationTokenRequest=>{:playerSessionID=>"111"}}
$ hash[:attributes!]
=> "" (here is the crazy result)
$ hash.class
=> Hash
$ hash.keys
=> [:createAuthenticationTokenRequest]
what is going on here? Am i not supposed to get nil for non existent hash keys ?
Detailed problem:
I am using savon to send a webservice request and getting "can't convert Symbol into Integer" error all the time, debugging the error with pry showed me that this line is getting executed as empty string which it shouldn't.
attributes = hash[:attributes!] || {}
Help me out here!
thanks in advance, cheers!
Update:
Answer for how the hash is created;
class Gyoku::Hash
def self.iterate_with_xml(hash)
xml = Builder::XmlMarkup.new
attributes = hash[:attributes!] || {}
Update2:
This is the request i am sending
request(
createAuthenticationTokenRequest: {
playerSessionID: "111"
}
)
As i mentioned before this is savon gem code that gets executed. I tried to write the question as less boring as possible, and don't get why it gets downvoted :/
here is the source code that gets debugged.
https://github.com/savonrb/gyoku/blob/master/lib/gyoku/hash.rb
i guess i deserved to be downvoted......
Don't do this in your code,
def default_request_parameters
#default_request_parameters || Hash.new('')
end
You can create a hash like this
way 1:
new_hash = Hash.new{|h,k| h[k] = ""}
new_hash['unknown_key']
it returns
=> ""
new_hash.keys
=> ['unknown_key']
this adds 'unknown_key' key to the hash.
way 2:
hash2 = Hash.new("")
hash2['unknown_key']
it returns
=> ""
but no keys are added.
hash2.keys
it returns
=> []

Ruby: How can I have a Hash take multiple keys?

I'm taking 5 strings (protocol, source IP and port, destination IP and port) and using them to store some values in a hash. The problem is that if the IPs or ports are switched between source and destination, the key is supposed to be the same.
If I was doing this in C#/Java/whatever I'd have to create a new class and overwrite the hashcode()/equals() methods, but that seems error prone from the little I've read about it and I was wondering if there would be a better alternative here.
I am directly copying a paragraph from Programming Ruby 1.9:
Hash keys must respond to the message hash by returning a hash code, and the hash code for a given key must not change. The keys used in hashes must also be comparable using eql?. If eql? returns true for two keys, then those keys must also have the same hash code. This means that certain classes (such as Array and Hash) can't conveniently be used as keys, because their hash values can change based on their contents.
So you might generate your hash as something like ["#{source_ip} #{source_port}", "#{dest_ip} #{dest_port}", protocol.to_s].sort.join.hash such that the result will be identical when the source and destination are switched.
For example:
source_ip = "1.2.3.4"
source_port = 1234
dest_ip = "5.6.7.8"
dest_port = 5678
protocol = "http"
def make_hash(s_ip, s_port, d_ip, d_port, proto)
["#{s_ip} #{s_port}", "#{d_ip} #{d_port}", proto.to_s].sort.join.hash
end
puts make_hash(source_ip, source_port, dest_ip, dest_port, protocol)
puts make_hash(dest_ip, dest_port, source_ip, source_port, protocol)
This will output the same hash even though the arguments are in a different order between the two calls. Correctly encapsulating this functionality into a class is left as an exercise to the reader.
I think this is what you mean...
irb(main):001:0> traffic = []
=> []
irb(main):002:0> traffic << {:src_ip => "10.0.0.1", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]
irb(main):003:0> traffic << {:src_ip => "10.0.0.2", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}, {:protocol=>"tcp", :src_ip=>"10.0.0.2", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]
The next, somewhat related, question is how to store the IP. You probably want to use the IPAddr object instead of just a string so you can sort the results more easily.
You can use the following code:
def create_hash(prot, s_ip, s_port, d_ip, d_port, value, x = nil)
if x
x[prot] = {s_ip => {s_port => {d_ip => {d_port => value}}}}
else
{prot => {s_ip => {s_port => {d_ip => {d_port => value}}}}}
end
end
# Create a value
h = create_hash('www', '1.2.4.5', '4322', '4.5.6.7', '80', "Some WWW value")
# Add another value
create_hash('https', '1.2.4.5', '4562', '4.5.6.7', '443', "Some HTTPS value", h)
# Retrieve the values
puts h['www']['1.2.4.5']['4322']['4.5.6.7']['80']
puts h['https']['1.2.4.5']['4562']['4.5.6.7']['443']

Resources