What is the difference between :something => true and something: true in Ruby? - ruby

I have this Capabara method that takes an option:
page.should have_selector("#jFooterStandardLinks", :visible => true)
The option can also be provided like:
page.should have_selector("#jFooterStandardLinks", visible: true)
Both methods work but I am getting an error in Eclipse IDE.
What is the difference between :visible => true and visible: true?
Is visible: still interpreted as a Ruby symbol?

There is no difference. symbol: value is an alias for :symbol => value, only that first is not compatible to ruby 1.8.

There's no difference. Ruby accepts key: value hash syntax while the keys are symbols. Thus
x_method #blah, some_key: 'asdf', another_key: 3, yet_a_key: true # is equivalent to:
x_method(#blah, {:some_key => 'adsf', :another_key => 3, :yet_a_key => true })
The first syntax is not available in ruby 1.8.7 as #ckruse noted.

The only difference is the transition from ruby 1.8x to 1.9x. For now it's still exactly the same, but it could be that :visible => true will eventually be deprecated in favor of visible: true.
The new syntax is slightly simpler and cleaner and has closer resemblance to JSON.
Concerning your second question, here's a nice quote I've found:
"The new notation is sort of a syntactic sugar for the most common style of hashes out there, the so called symbol to object hash. If you do this in the irb, you’ll see ruby returning the old school hash, with the symbols used as keys:"
new_hash = {simon: "Talek", lorem: "Ipsum"}
# => {:simon=>"Talek", :lorem=>"Ipsum"}
"If you need to have arbitrary objects as your hash keys, you’ll still have to do it old school."
Source: http://breakthebit.org/post/8453341914/ruby-1-9-and-the-new-hash-syntax

Related

Hash syntax strangeness [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there any difference between the :key => “value” and key: “value” hash notations?
What's the difference between this:
method: :delete
and this?
:method => :delete
I'm guessing it has to do with different versions of Rails but not sure. I have only worked in Rails 3.x.
They are completely equivalent, except the first can only be used since ruby 1.9 (and higher, of course).
In ruby 1.8 the hash syntax used the =>, also known as the hash rocket. You could put anything in front, and anything behind, but the thing in front is your key, behind the value. If you have a symbol as key, and a symbol as value, you would write:
:method => :delete
But you could also write
{ 1 => 'one', :2 => 'two', 'THREE' => 3 }
Now, for ruby 1.9.x, a new shorter syntax was introduced. Since most people use symbols as keys, you can now write:
method: :delete
Which is just a shorter/cleaner version. Also note that it is possible to mix both styles, which in some cases is needed.
E.g. in ruby 1.8 you would write:
{ :class => 'smthg', :'data-type' => 'a type' }
This would translate to the following in ruby 1.9
{ class: 'smthg', :'data-type' => 'a type' }
Note that you can still keep using the "old" hash syntax as well. It is a matter of preference. Personally for hashes with only symbols as keys, I use the clean/short version. I generally try not to mix hash-style in a single hash :)

Allowing for Ruby 1.9's hash syntax?

Although I've been using Ruby 1.9 for a while, I only recently discovered the newer hash syntax that's now supported:
settings = {
host: "localhost",
port: 5984
}
As opposed to:
settings = {
"host" => "localhost"
}
I like its similarity to JavaScript's object noation, and looks a bit like JSON, so I'll probably switch to using it with all my libraries, but I still want to support other users and my own projects which assume the old syntax.
So it really comes down to a fairly simple question of having to test for both symbols and strings. Is there an easy way to do both of these lines as one?
return true if settings["host"] and settings["db"]
return true if settings[:host] and settings[:db]
Even in Ruby < 1.9, you could use symbols for keys. For example:
# Ruby 1.8.7
settings = { :host => "localhost" }
puts settings[:host] #outputs localhost
settings.keys[0].class # => Symbol
Ruby 1.9 changes the way that you create hashes. It takes the key and converts it to a symbol for you, while eliminating the need for a hash rocket.
# Ruby 1.9.2
settings = { host: "localhost" }
settings[:host] # => "localhost"
settings.keys[0].class # => Symbol
In both cases, if I try to access settings[:name] with settings["name"], I'm going to get nil. All Ruby 1.9 does is allow for a new way of creating hashes. To answer your question, you cannot, as far as I know, use the new {key: value} syntax if you want backwards compatibility with Ruby 1.8.
ActiveSupport (from Rails) offers HashWithIndifferentAccess. You will need to explicitly use it instead of a standard Hash.
Beware though, a quote from the class itself:
This class has dubious semantics and we only have it so that people
can write params[:key] instead of params[‘key’] and they get the same
value for both keys.
So it really comes down to a fairly simple question of having to test for both symbols and strings. Is there an easy way to do both of these lines as one?
return true if settings["host"] and settings["db"]
return true if settings[:host] and settings[:db]
I'm not sure what you're really asking, because this doesn't seem totally related to the original title, but try:
# somewhere you get the values you are going to need to look up...
host = 'foo'
db = 'bar'
# then code goes by...
return true if settings[host.to_sym] and settings[db.to_sym]
# later you assign a symbol to one of the keys:
host = :foo
# more code goes by...
return true if settings[host.to_sym] and settings[db.to_sym]
It's all the same. Let Ruby covert from strings to symbols as necessary.
This works because:
'foo'.to_s # => "foo"
:foo.to_s # => "foo"
'foo'.to_sym # => :foo
:foo.to_sym # => :foo
You pick whether you're going to use symbols or strings for hash keys and let Ruby sort it out.

Unique construct for passing a hash

I have never seen this construct for building a hash. do_stuff(records: records) Does this only work in a parameter list being sent to a method? Is it documented anywhere? I know it is Ruby 1.9+.
records = {
'example.com' => '1.2.3.4',
'hello.com' => '44.33.22.22',
}
def do_stuff(data = {} )
puts data
end
do_stuff(records: records)
There are two things going on here. The { key: value } syntax is new in Ruby 1.9. It is equivalent to { :key => value }.
Also, Ruby methods have some syntactical sugar that allows you to pass in a hash literal as the last argument of the method without including the curly braces. This is not new in Ruby 1.9. So
do_stuff(key: value)
Is equivalent to
do_stuff({ key: value })
Just to remind you, this only works if the hash is the last argument to the method.
The new syntax for Hashes in Ruby 1.9 allows you to drop the hash rocket.
#Pre 1.9
{:key => value}
#1.9+
{key: value}
Both of the above are equivalent.
One thing to keep in mind when using the new hash syntax is that the key will always be treated as a symbol.

Inconsistent implicit hash creation in Ruby?

Ok, so I was comparing some stuff in my own DSL to Ruby. One construct they both support is this
x=["key" => "value"]
Knowing the difference between arrays and hashes, I would think this to be illegal, but the result in Ruby is
[{"key" => "value"}]
Why is this? And with this kinda syntax why can't you do
x=("key" => "value")
Why is an array a special case for implicitly created hashes?
Another special case is in a function call, consider:
def f(x)
puts "OK: #{x.inspect}"
end
f("foo" => "bar")
=> OK: {"foo"=>"bar"}
So in some contexts, Hashes can be built implicitly (by detecting the => operator?). I suppose the answer is just that this was Matz's least-surprising behavior.
With this apparent inconsistency in implicit hash creation, ruby achieves consistency in this regard:
func(whatever...)
can always be substituted with:
args = [whatever...]
func(*args)
You can convert between argument lists and arrays, and therefore it is logical that they have the same syntax.
I would say that the interpreter figures out that "key" => "value" is a hash, the same way it would figure out that 5 is a number when you put it into an array.
So if you write:
x = [5]
The interpreter is not going to think that it is a string, and return:
x = ["5"]
It seems that ruby implicitly creates hashes in some instances.

Ruby => operator... eg: :text => /Log In/

What does this do? I find the example here, but other than what it does, what does it mean? I can't find anything on google because well, I am not sure what '=>' is even called in this context.
More examples here:
http://mechanize.rubyforge.org/mechanize/EXAMPLES_rdoc.html
In :text => /Log In/, you are passing a hash to page's link_with function, and the key in the hash is :text and its corresponding value is /Log In/.
Basically: :x => y means that :x is a key in a hash that maps to a value of y.
passing hashes to functions like this allows you to have something like (but not exactly) named parameters.
UPDATE:
A symbol of the form :something is called.... a symbol! You can think of them sort of like global string constants (but they're not quite the same). Now, when you think back to something like:
login_page.form_with(:action => '/account/login.php')
What you're actually doing is constructing a new hash on the fly. You create a new element in the hash, where the key is a string with the value "action", and the value of that element is "/account/login.php" (in this case, also a string, but I'm pretty sure you can store other things in hashes besides strings).
...whew! It's been a while since I've worked with Ruby. I hope I got that all correct. ;)
Some good looking pages here (more can be found by searching google for "ruby symbol")
http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols
http://www.troubleshooters.com/codecorn/ruby/symbols.htm#_What_are_symbols
It associates a value with an index for hashes.
obj.method :text => /Log In/
is shorthand for
obj.method {:text => /Log In/}
It's used to create a hash expression, as in { key => value }.
Also, when used as the last parameter in a method call, the { } are not needed, so the key => value can appear alone.
>> p({:a => 1, :b => 2})
{:a=>1, :b=>2}
=> nil
>> p :c=>3, :d=>4
{:d=>4, :c=>3}
=> nil
>> t = { :e=>5, :f=>6 }
=> {:f=>6, :e=>5}
This shorthand is really nice in poetry mode, where a literal hash following a method name would look like a block.

Resources