Pulling out values from element of array - ruby

I have a hash that is generated by IB-ruby and looks like this:
{:contract=>#<IB::Stock:0x0000560721a1aee0 #attributes={:symbol=>"AAPL", :currency=>"USD", :sec_type=>"STK", :created_at=>2019-10-23 23:03:35 +0200, :con_id=>0, :right=>"", :include_expired=>false, :exchange=>"SMART"}>, :last_price=>0.24308e3, :high=>0.24324e3, :low=>0.24122e3, :close_price=>0.23996e3, :open_tick=>0.2421e3, :bid_price=>0.2431e3, :ask_price=>0.24319e3}
How do I pull out the symbol ("AAPL") and the closing_price (0.23996e3) for further processing?

What you posted is the string representation of a Hash.
This Hash has a key :close_price, whose value you can access in this way:
your_hash[:close_price] #=> 0.23996e3
The hash also has a key :contract whose value is an instance of the class IB::Stock. To access this object:
ib_stock_instance = your_hash[:contract]
ib_stock_instance.class #=> IB::Stock

Related

Accessing specific attribute of an object

Hello I have the following object
object = [#<ShopifyAPI::DiscountCode:0x000000000e1c78a8 #attributes={"code"=>"Disc2", "amount"=>"1.00", "type"=>"percentage"}, #prefix_options={}, #persisted=true>]
How can I properly access the "code" name of that object?
I have tried object[:code] and object.code but it appears I am overlooking something.
object is an array of ShopifyAPI::DiscountCode.
The best way to access it is
object[0].attributes['code']
If u want code of all the objects available in the array, you could get the array of values by
object.map { |obj| obj.attributes['code'] }
Given that this is an Array of ShopifyAPI::DiscountCodes (which inherit from ActiveResource::Base)
You can call the code method on them. eg:
object[0].code
#=> "Disc2"
object.map(&:code)
#=> ["Disc2"]
First, object is array:
obj0 = object[0]
Second, this is instance variable:
attributes = obj0.instance_variable_get(:#attributes)
Last, gets values by keys:
attributes['code']

Hyphens in serialized JSON OpenStruct

I have a JSON object such as:
"c": {
"10-20": 9.0,
"0-10": 8.5,
"30-end": 5.085714285714286,
"20-30": 10.3
}
When I convert that JSON to a serialized object using:
JSON.parse(response.body, object_class: OpenStruct)
It gives me:
<OpenStruct 10-20=0, 0-10=8.5, 30-end=5.085714285714286, 20-30=10.3>
Naturally that can't be accessed with c.10-20 as I don't believe hyphens are valid class variable names. So, how do you access these values?
You can use square brackets like you would with a hash:
obj["10-20"]
#=> 0
Of course, if most of the keys are not valid method names anyway, then you might as well just use a hash and not bother with an OpenStruct.
Related documentation: OpenStruct#[]

Ruby Array Attributes

I am trying to access the Shopify API using the shopify-api gem. In particular, I am trying to access the price of an item, which is contained in an array.
product = ShopifyAPI::Product.find(id)
variant = product.variants
variant here is an array, and when I do puts variant.inspect, I get
[
#<ShopifyAPI::Variant:0x000000041c9e50 #attributes={
"id"=>23923477191,
"title"=>"Default Title",
"price"=>"6.00",
"sku"=>"shirts",
"position"=>1,
"grams"=>0,
"inventory_policy"=>"deny",
"compare_at_price"=>nil,
"fulfillment_service"=>"manual",
"inventory_management"=>"shopify",
"option1"=>"Default Title",
"option2"=>nil,
"option3"=>nil,
"created_at"=>"2016-06-30T14:06:07-04:00",
"updated_at"=>"2016-07-16T19:00:07-04:00",
"taxable"=>true,
"barcode"=>"",
"image_id"=>nil,
"inventory_quantity"=>1,
"weight"=>0.0,
"weight_unit"=>"kg",
"old_inventory_quantity"=>1,
"requires_shipping"=>true
}, #prefix_options={:product_id=>7509869767}, #persisted=true>
]
How do I access/change 'price' under '#attributes`?
Attributes are what Ruby calls object properties. Just access it as you would a property in most other languages.
Get the item of the array you want (0 in this example) and then access the price attribute
variant[0].price
Use:
variant.first["price"]
The variant array has 3 elements; the #attributes element is the first.
This #attributes element is a hash map, and you are looking for the value at key "price".

Display multiple hash keys notation

Let's say i have a ruby hash in the style of savon soap xml response to hash
hash1= { node1­: {node­2:{node3:1­,node4:2}}­}
now to display this hash
hash1[:nod­e1][:node2­][:node3]
works and outputs => 1
hash1[:nod­e1][:node2­][:node4]
works and output => 2
hash1[:nod­e1][:node2­][:node3][:node4]
gives TypeError
although i have seen that type of code on savon scripts. What doesnt it work in my situation ?
hash1[:nod­e1][:node2­][:node3][:node4] is calling the method [] on
hash1[:nod­e1][:node2­][:node3].
Its the equivalent of trying 1[:node4]. The method on an integer takes a Fixnum and cannot implicitly convert a symbol (or a string etc) into an integer.
These multiply-nested hashes are difficult to read, aren't they? Let's spread your hash out a bit:
hash1= {
node1­: {
node­2: { node3:1­, node4:2 }
}­
}
So: The value of node1 is itself a hash. The only entry in that hash, node2, also has a hash for a value. This hash has two entries: node3 and node4, both of which have integers as values.
So hash1[:node1][:node2] returns {node3:1, node4:2}. And hash1[:node1][:node2][:node3] returns 1.
But hash1[:node1][:node2][:node3][:node4] doesn't make any sense, because 1 isn't a hash, and therefore doesn't have a key :node4. That key belongs to the :node2 hash.
It would make sense if you had hash1= { node1­: {node­2: {node3: {node4:2} }}­}. But you don't.
Like I said: these nested hashes are a pain to read...

how to find a hash key with one of the predefined names?

I have a hash with an arbitrary key:
{'GET': [1,2,3]}
or
{'POST': ['my data 0', 'my data 1']}
The hash is generated from JSON which is sent in the request body. There is just one key, or rather, I ignore any keys but one.
I want to find which key it is, and this is the code that I wrote:
items = data['GET'] || data['get'] || data['POST'] || data['post']
this does not look neat. If the number of keys that I want to process grows the expression will be long. I want it to be short. I am new to Ruby, is there a better way?
If you think it might grow, you may want to separate the HTTP methods from the finding of that method in the data:
methods = [:get, :post]
def find_method(data)
keys = methods.map{|m| [m.to_s.upcase, m.to_s]}.flatten
data.values_at(keys).first
end
You could just get the first value (assuming there's only one) like this:
item = data.values.first
You could use the Hash#values_at method.
http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-values_at
data.values_at('GET','get', 'POST','post').first

Resources