Hash syntax strangeness [duplicate] - ruby

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 :)

Related

What's the difference between a hash with => and : [duplicate]

This question already has answers here:
Is there any difference between the `:key => "value"` and `key: "value"` hash notations?
(5 answers)
Closed 2 years ago.
I use a specific library where I can pass variables with such an hash:
{ 'username' = > 'John'}
But when I try to pass the variables with such an hash:
{ 'username': 'John' }
It doesn't work. I always thought => is the old syntax for : but there seems to be really a difference.
Code where it's used: Liquid::Template.parse(template).render!(variables).html_safe
Can you please explain the difference and tell me how I can convert such an hash: { 'username': 'John' } to this { 'username' = > 'John'} presentation?
{ some_arbitrary_expression(some_argument, arg2) => another_arbitrary_expression(arg) }
Is the general syntax for Hash literals. Any object that responds to hash and eql? can be used as a key in a Hash.
{ some_valid_symbol: arbitrary_expression(arg1, arg2) }
Is the "new-style" Hash literal syntax for Symbol keys.
I always thought => is the old syntax for : but there seems to be really a difference.
I'm not sure where you were taught this, but I sure would like to know so I can warn others about this source. It has never been true, there are no current plans to make it true, and it probably never will be true. To my knowledge, there is nothing in the official documentation, in the RubySpec, or in any of the well-known books (The Ruby Programming Language, Programming Ruby) that says it either.
Can you please explain the difference and tell me how I can convert such an hash: { 'username': 'John' } to this { 'username' = > 'John'} presentation?
You can change the String representation of a Hash by monkey-patching Hash#to_s or Hash#inspect, but it is unclear what that would buy you.
If a method you are using expects a Hash whose keys are Strings and you pass it a Hash whose keys are Symbols, then changing the String representation of the Hash is not going to help you. You need to fix the source and make sure that your keys are Strings.

What is the difference between `:limit` and `limit:`? [duplicate]

This question already has answers here:
Is there any difference between the `:key => "value"` and `key: "value"` hash notations?
(5 answers)
Closed 7 years ago.
What is the difference between :limit and limit:? I am assuming the first is the method for limiting entry size in Ruby on Rails. What is the second for? I also don't know what is the significance of putting column n on the right side.
This is probably an issue with hash notation.
Ruby 1.8 and prior use a style like this:
method(:limit => 10)
Ruby 1.9 and more recent have a new style that looks like:
method(limit: 10)
The new notation is a lot more like that in other languages like Python and JavaScript. They are functionally identical, though, as you can check with irb where it always shows in conventional notation:
{ test: 'value' }
# => { :test => 'value' }
As to your question as to what limit means, it really depends on what method you're passing this in to. In the context of a schema definition it can limit the size of a field:
t.string limit: 1024
If it's in the context of a query it might limit the number of results returned. Each method has their own interpretation so you'll need to consult the documentation on each method you encounter.
:limit is a value of type symbol. You can see more about symbols on Ruby docs. http://ruby-doc.org/core-2.2.2/Symbol.html
limit: is a syntactic sugar and can be used only as a hash key when this key is a symbol. Example: { :limit => 10 } is the traditional way. After Ruby 1.9.3 you can rewrite that like { limit: 10 }
Variables that have a colon : before their name denounces that they are symbols (unique identifier) and this means that it is possible to do the following:
symbol = :limit
using the colon after the name is usually meant to indicate a hash key, such as the following:
hash = { limit: 5 }
puts hash[:limit] # returns 5
The confusion often ensues when working with older versions of ruby, where hashes are written as follows:
hash = { :limit => 5 }
puts hash[:limit] # returns 5
Which has the same exact meaning as the above statement.

Rails Hash Format

Which is the preferred hash format for Rails? Or is one of them wrong?
User.create(:name => "John")
or
User.create(name: "John")
Can I do
User.create(:name "John")
or
User.create(name: => "John")
The ruby 1.9's way is to do User.create(name: 'John'). The older fashion is to do User.create(:name => 'John'). Other solutions will not works.
You just need to realise the semantics of the different symbols.
In here:
User.create(:name => "John")
You have a symbol :user mapped with linking operator=>.
In here:
User.create(name: "John")
You have linking operator :.
These two are wrong:
User.create(:name "John")
Here you have symbol and then no link from key to value at all.
This too:
User.create(name: => "John")?
You have two links once : and once =>.
I think your biggest issue is that you do not completely undertand the meaning of symbols in Ruby. Read here.
Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
If you want to study rails, I highly recommend a git repo(https://github.com/bbatsov/rails-style-guide), it can help you write good style rails code, hopefully useful to you.

What is the difference between :something => true and something: true in 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

Is there any difference between the `:key => "value"` and `key: "value"` hash notations?

Is there any difference between :key => "value" (hashrocket) and key: "value" (Ruby 1.9) notations?
If not, then I would like to use key: "value" notation. Is there a gem that helps me to convert from :x => to x: notations?
Yes, there is a difference. These are legal:
h = { :$in => array }
h = { :'a.b' => 'c' }
h[:s] = 42
but these are not:
h = { $in: array }
h = { 'a.b': 'c' } # but this is okay in Ruby2.2+
h[s:] = 42
You can also use anything as a key with => so you can do this:
h = { C.new => 11 }
h = { 23 => 'pancakes house?' }
but you can't do this:
h = { C.new: 11 }
h = { 23: 'pancakes house?' }
The JavaScript style (key: value) is only useful if all of your Hash keys are "simple" symbols (more or less something that matches /\A[a-z_]\w*\z/i, AFAIK the parser uses its label pattern for these keys).
The :$in style symbols show up a fair bit when using MongoDB so you'll end up mixing Hash styles if you use MongoDB. And, if you ever work with specific keys of Hashes (h[:k]) rather than just whole hashes (h = { ... }), you'll still have to use the colon-first style for symbols; you'll also have to use the leading-colon style for symbols that you use outside of Hashes. I prefer to be consistent so I don't bother with the JavaScript style at all.
Some of the problems with the JavaScript-style have been fixed in Ruby 2.2. You can now use quotes if you have symbols that aren't valid labels, for example:
h = { 'where is': 'pancakes house?', '$set': { a: 11 } }
But you still need the hashrocket if your keys are not symbols.
key: "value" is a convenience feature of Ruby 1.9; so long as you know your environment will support it, I see no reason not to use it. It's just much easier to type a colon than a rocket, and I think it looks much cleaner. As for there being a gem to do the conversion, probably not, but it seems like an ideal learning experience for you, if you don't already know file manipulation and regular expressions.
Ruby hash-keys assigned by hash-rockets can facilitate strings for key-value pairs (e.g. 's' => x) whereas key assignment via symbols (e.g. key: "value" or :key => "value") cannot be assigned with strings. Although hash-rockets provide freedom and functionality for hash-tables, specifically allowing strings as keys, application performance may be slower than if the hash-tables were to be constructed with symbols as hash-keys. The following resources may be able to clarify any differences between hashrockets and symbols:
Ryan Sobol's Symbols in Ruby
Ruby Hashes Exaplained by Erik Trautman
The key: value JSON-style assignments are a part of the new Ruby 1.9 hash syntax, so bear in mind that this syntax will not work with older versions of Ruby. Also, the keys are going to be symbols. If you can live with those two constraints, new hashes work just like the old hashes; there's no reason (other than style, perhaps) to convert them.
Doing :key => value is the same as doing key: value, and is really just a convenience. I haven't seen other languages that use the =>, but others like Javascript use the key: value in their Hash-equivalent datatypes.
As for a gem to convert the way you wrote out your hashes, I would just stick with the way you are doing it for your current project.
*Note that in using key: value the key will be a symbol, and to access the value stored at that key in a foo hash would still be foo[:key].

Resources