What does a hash without a key mean in Ruby? - ruby

What does the {TOKEN} and {ACCOUNT_ID} mean in the following Ruby?
my_function({
:amount => 2000,
:currency => "usd",
:source => {TOKEN},
:destination => {ACCOUNT_ID}
})
I have Ruby 2.3.1 and am getting an error syntax error, unexpected '}', expecting => (SyntaxError)

A hash needs to be defined as either empty or with key, value pairs (see here). I'm guessing if you are following some sort of a tutorial, you need to fill those values in with some constants.
Usually variables in CAPS are constants, but it is possible to define a method in caps. Even so, one would need to call it explicitly with braces, as in TOKEN() and I can't think of anything that could be put inside curly braces to initialize a hash of some sort.

You probably need to end up with a structure like this:
my_function({
:amount => 2000,
:currency => "usd",
:source => "THE TOKEN",
:destination => "THE ACCOUNT ID"
})
or
my_function({
:amount => 2000,
:currency => "usd",
:source => "ckjnsdncc98n9dnx93d372n",
:destination => 123456
})
The {X} syntax looks like it's used as a placeholder for either Strings or numbers (most likely Strings)

Related

Isolating and displaying a specific element within a hash

I am currently having trouble writing a test that addresses the eligibility_settings of a record I have. I am having trouble pulling out one of the specific elements from this hash.
Specifically I want to test that by making a change elsewhere in a different function that changes the min age of a specific player, and so what I am really trying to test is the eligibility_settings.min_age. But i'm having trouble within my test isolating that out.
My hash looks like this
{
:name => "player1",
:label => "redTeam_1_1",
:group => "adult",
:teamId => 7,
:eligibility_settings => {
"min_age" => 18,
"player_gender" => "female",
"union_players_only" => true
}
}
However when I try looping through this hash, I am having trouble isolating that one element.
i've tried something like
team.get_players.first.map do |settings, value|
value.tap do |x, y|
y[3]
end
end
However It seems like what i've been trying, and my approach has not been working quite right.
Would anyone have any idea what I could do with this?
Although #SergioTulentsev gave the proper response, in the future if you are going to be looping through hashes, below is one way to iterate through the keys and grab the value you want.
hash = {
:name => "player1",
:label => "redTeam_1_1",
:group => "adult",
:teamId => 7,
:eligibility_settings => {
"min_age" => 18,
"player_gender" => "female",
"union_players_only" => true
}
}
hash.map do |settings, value|
p hash[:eligibility_settings]['min_age'] if settings == :eligibility_settings
end # output 18

How can I access or assign custom currency symbols when format method is called using money gem?

I have a list of currency codes that I need to display specific currency values for and have found that some are available in alternate_symbols from money gem. I can't figure out how to access those when using the format method, though, and also need to override a handful. For example, for CAD, I need to display the second symbol - CAD$ - but for SRD, I need to display SRD$ which doesn't exist in alternate_symbols array for that currency.
I'm looking to use i18n to specify these currencies since some are more custom.
One option is to override the necessary languages.
josh_dollar = {
:priority => 1,
:iso_code => "USD",
:iso_numeric => "840",
:name => "United States Dollar",
:symbol => "Josh",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
}
Money::Currency.register(josh_dollar)
josh_dollar = Money.new(1000,"USD")
josh_dollar.format
#=> "10.00 Josh"

How to pass the second parameter to Mongo::Collection#find?

This is a newbie question. I find the method definition in the YARD Rdoc:
(Object) find(selector = {}, opts = {})
Options Hash (opts):
:fields (Array, Hash)
then I try this coll.find('English' => 'fulcrum',{English:1,Chinese:1}), want the result 'English' field is fulcrum ,and only return English and Chinese field, but Ruby punished me with the this
irb(main):018:0> coll.find('English' => 'fulcrum',{English:1,Chinese:1})
SyntaxError: (irb):18: syntax error, unexpected ')', expecting tASSOC
from /usr/local/bin/irb:12:in `<main>'
irb(main):019:0>
I want to know why, thanks
after correct the syntax problem by the suggestion by #mu, I got Unknown options error:
irb(main):013:0> coll.find({English:'fulcrum'},{English:1, :Chinese => 1})RuntimeError: Unknown options [{:English=>1, :Chinese=>1}]
from /usr/local/lib/ruby/gems/1.9.1/gems/mongo-1.5.2/lib/mongo/collection.rb:234:in `find'
from (irb):13
from /usr/local/bin/irb:12:in `<main>'
irb(main):014:0>
When Ruby sees an unwrapped Hash in argument list:
o.m(k => v, ...)
it assumes that you really mean this:
o.m({ k => v, ... })
So, when you say this:
coll.find('English' => 'fulcrum', {English: 1, Chinese: 1})
Ruby sees this:
coll.find({ 'English' => 'fulcrum', {English: 1, Chinese: 1} })
A Hash is a perfectly valid key so Ruby expects it to be followed by a => value:
coll.find('English' => 'fulcrum', {English: 1, Chinese: 1} => some_value)
and that's where the error message comes from:
syntax error, unexpected ')', expecting tASSOC
If you want to pass two hashes, you need to wrap the first one in braces:
coll.find({'English' => 'fulcrum'}, {English: 1, Chinese: 1})
The second argument to [find](
http://api.mongodb.org/ruby/current/Mongo/Collection.html#find-instance_method) should be an options Hash and it looks like you want the :fields option and you can give that an array of names instead of a noisy Hash:
coll.find({'English' => 'fulcrum'}, :fields => %w[English Chinese])

Ruby: Create hash with default keys + values of an array

I believe this has been asked/answered before in a slightly different context, and I've seen answers to some examples somewhat similar to this - but nothing seems to exactly fit.
I have an array of email addresses:
#emails = ["test#test.com", "test2#test2.com"]
I want to create a hash out of this array, but it must look like this:
input_data = {:id => "#{id}", :session => "#{session}",
:newPropValues => [{:key => "OWNER_EMAILS", :value => "test#test.com"} ,
{:key => "OWNER_EMAILS", :value => "test2#test2.com"}]
I think the Array of Hash inside of the hash is throwing me off. But I've played around with inject, update, merge, collect, map and have had no luck generating this type of dynamic hash that needs to be created based on how many entries in the #emails Array.
Does anyone have any suggestions on how to pull this off?
So basically your question is like this:
having this array:
emails = ["test#test.com", "test2#test2.com", ....]
You want an array of hashes like this:
output = [{:key => "OWNER_EMAILS", :value => "test#test.com"},{:key => "OWNER_EMAILS", :value => "test2#test2.com"}, ...]
One solution would be:
emails.inject([]){|result,email| result << {:key => "OWNER_EMAILS", :value => email} }
Update: of course we can do it this way:
emails.map {|email| {:key => "OWNER_EMAILS", :value => email} }

Easiest Way to Print Non-Strings in Ruby

I'm constantly doing this
puts “The temperature is “ + String(temperature) + “.”
in my debugging code, and another option is to use interpolation
puts “The temperature is #{temperature}.”
is there any less cumbersome way to do this?
Edit: This is just for debugging, if that matters.
None that are all that worthwhile for small cases like that.
Though, you should prefer interpolation as it's less expensive than concatenation.
The best way to insert dynamic variables into strings is
#interpolation
"foo #{my_var} bar"
It will call the to_s method on whatever object the expression returns and insert that string. It really the same as
#concatenation
"foo " + my_var.to_s + " bar"
But, as wfarr metioned, its faster to do interpolation. Easier to read too.
A slightly different approach is to use assertions in automated tests.
For example using Test::Unit :-
assert_equal 25, temperature
I find that using automated tests dramatically cuts down on the amount of debugging code I have to write.
Use Kernel#p
p temperature #=> 10.25
When I'm debugging, I often label such statements just by copying the line, and using inserting a colon, making the variable into a symbol.
p :attributes #=> :attributes
p attributes #=> { :mood => "happy", 5 => [] }
Or
p [:location, location] #=> [ :location, "# work" ]
Note that Kernel#p calls #inspect on its arguments, instead of #to_s, but this normally provides more useful debugging info anyway.
I highly recommend to use irbtools gem which includes awesome_print or just awesome_print.
I personally find it faster and less cumbersome to use in dev, then using interpolated strings, thou sometimes that's the only way to go.
You can do this on any object and it will give you a nicely formatted otput be that array, string or hash or even any other complex object that you may have - like 3-dimentional array printted as a tree structure. In order to have it awailable in your rails env - just include it in the Gemfile in the development group, or add it to .irbrc - to always have it in your irb console. Then just do
require "awesome_print"
ap MyGreatObject
here is a sample output from one of my projects
ap Address
class Address < ActiveRecord::Base {
:id => :integer,
:address_line_1 => :string,
:address_line_2 => :string,
:address_line_3 => :string,
:city => :string,
:state => :string,
:zip => :string,
:country => :string,
:attn => :string,
:category_id => :integer,
:addressable_id => :integer,
:addressable_type => :string,
:created_at => :datetime,
:updated_at => :datetime
}
ap Address.first
Address Load (1.0ms) SELECT `addresses`.* FROM `addresses` LIMIT 1
#<Address:0x7bc5a00> {
:id => 1,
:address_line_1 => "1 Sample Drive",
:address_line_2 => nil,
:address_line_3 => nil,
:city => "Chicago",
:state => "IL",
:zip => "60625",
:country => "USA",
:attn => nil,
:category_id => 1,
:addressable_id => 1,
:addressable_type => "Warehouse",
:created_at => Tue, 10 Jan 2012 14:42:20 CST -06:00,
:updated_at => Tue, 17 Jan 2012 15:03:20 CST -06:00
}
There's always the possibility to use printf style formatting:
"The temperature is %s" % temperature
This would allow for finer formatting of numbers, etc. as well. But honestly, how much less "cumbersome" than using #{} interpolation can you expect to get?
Another way is to do something stupid like this:
"The temperature is %s." % temperature.to_s
Personally I'd use interpolation

Resources