What does :this means in Ruby on Rails? - ruby

I'm new to the Ruby and Ruby on Rails world. I've read some guides, but i've some trouble with the following syntax.
I think that the usage of :condition syntax is used in Ruby to define a class attribute with some kind of accessor, like:
class Sample
attr_accessor :condition
end
that implicitly declares the getter and setter for the "condition" property.
While i was looking at some Rails sample code, i found the following examples that i don't fully understand.
For example:
#post = Post.find(params[:id])
Why it's accessing the id attribute with this syntax, instead of:
#post = Post.find(params[id])
Or, for example:
#posts = Post.find(:all)
Is :all a constant here? If not, what does this code really means? If yes, why the following is not used:
#posts = Post.find(ALL)
Thanks

A colon before text indicates a symbol in Ruby. A symbol is kind of like a constant, but it's almost as though a symbol receives a unique value (that you don't care about) as its constant value.
When used as a hash index, symbols are almost (but not exactly) the same as using strings.
Also, you can read "all" from :all by calling to_s on the symbol. If you had a constant variable ALL, there would be no way to determine that it meant "all" other than looking up its value. This is also why you can use symbols as arguments to meta-methods like attr_accessor, attr_reader, and the like.
You might want to read up on Ruby symbols.

:all is a symbol. Symbols are Ruby's version of interned strings. You can think of it like this: There is an invisible global table called symbols which has String keys and Fixnum values. Any string can be converted into a symbol by calling .to_sym, which looks for the string in the table. If the string is already in the table, it returns the the Fixnum, otherwise, it enters it into the table and returns the next Fixnum. Because of this, symbols are treated at run-time like Fixnums: comparison time is constant (in C parlance, comparisons of symbols can be done with == instead of strcmp)
You can verify this by looking at the object_id of objects; when two thing's object_ids are the same, they're both pointing at the same object.
You can see that you can convert two strings to symbols, and they'll both have the same object id:
"all".to_sym.object_id == "all".to_sym.object_id #=> true
"all".to_sym.object_id == :all.object_id #=> true
But the converse is not true: (each call to Symbol#to_s will produce a brand new string)
:all.to_s.object_id == :all.to_s.object_id #=> false

Don't look at symbols as a way of saving memory. Look at them as indicating that the string ought to be immutable. 13 Ways of Looking at a Ruby Symbol gives a variety of ways of looking at a symbol.
To use a metaphor: symbols are for multiple-choice tests, strings are for essay questions.

This has nothing to do with Rails, it's just Ruby's Symbols. :all is a symbol which is effectively just a basic string.

Related

Ruby to_s a special method? [duplicate]

I'm learning Ruby and I've seen a couple of methods that are confusing me a bit, particularly to_s vs to_str (and similarly, to_i/to_int, to_a/to_ary, & to_h/to_hash). What I've read explains that the shorter form (e.g. to_s) are for explicit conversions while the longer form are for implicit conversions.
I don't really understand how to_str would actually be used. Would something other than a String ever define to_str? Can you give a practical application for this method?
Note first that all of this applies to each pair of “short” (e.g. to_s/to_i/to_a/to_h) vs. “long” (e.g. to_str/to_int/to_ary/to_hash) coercion methods in Ruby (for their respective types) as they all have the same semantics.
They have different meanings. You should not implement to_str unless your object acts like a string, rather than just being representable by a string. The only core class that implements to_str is String itself.
From Programming Ruby (quoted from this blog post, which is worth reading all of):
[to_i and to_s] are not particularly strict: if an object has some kind of decent representation as a string, for example, it will probably have a to_s method… [to_int and to_str] are strict conversion functions: you implement them only if [your] object can naturally be used every place a string or an integer could be used.
Older Ruby documentation from the Pickaxe has this to say:
Unlike to_s, which is supported by almost all classes, to_str is normally implemented only by those classes that act like strings.
For example, in addition to Integer, both Float & Numeric implement to_int (to_i's equivalent of to_str) because both of them can readily substituted for an Integer (they are all actually numbers). Unless your class has a similarly tight relationship with String, you should not implement to_str.
To understand if you should use/implement to_s/to_str, let's look at some exemples. It is revealing to consider when these method fail.
1.to_s # returns "1"
Object.new.to_s # returns "#<Object:0x4932990>"
1.to_str # raises NoMethodError
Object.new.to_str # raises NoMethodError
As we can see, to_s is happy to turn any object into a string. On the other hand, to_str raises an error when its parameter does not look like a string.
Now let us look at Array#join.
[1,2].join(',') # returns "1,2"
[1,2].join(3) # fails, the argument does not look like a valid separator.
It is useful that Array#join converts to string the items in the array (whatever they really are) before joining them, so Array#join calls to_s on them.
However, the separator is supposed to be a string -- someone calling [1,2].join(3) is likely to be making a mistake. This is why Array#join calls to_str on the separator.
The same principle seems to hold for the other methods. Consider to_a/to_ary on a hash:
{1,2}.to_a # returns [[1, 2]], an array that describes the hash
{1,2}.to_ary # fails, because a hash is not really an array.
In summary, here is how I see it:
call to_s to get a string that describes the object.
call to_str to verify that an object really acts like a string.
implement to_s when you can build a string that describes your object.
implement to_str when your object can fully behave like a string.
I think a case when you could implement to_str yourself is maybe a ColoredString class -- a string that has a color attached to it. If it seems clear to you that passing a colored comma to join is not a mistake and should result in "1,2" (even though that string would not be colored), then do implement to_str on ColoredString.
Zverok has a great easily understandable article about when to use what (explained with to_h and to_hash).
It has to do whether your Object implementing those methods can be converted to a string
-> use to_s
or it is a type of some (enhanced) string
-> use to_str
I've seen a meaningful usage of to_hash in practice for the Configuration class in the gem 'configuration' (GitHub and Configuration.rb)
It represents -- as the name says -- the provided configuration, which in fact is a kind of hash (with additional features), rather than being convertible to one.

Ruby koan 124 - Are these symbols spontaneously changing type?

I'd like to get a categorical answer on how (and why) symbols appear to change type.
I had learned that symbols that end with a colon were an alternate syntax for declaring a symbol, usually used to populate hashes.
Koan number 124 has added more ambiguity to my (non)understanding by doing the following:
def method_with_keyword_arguments(one: 1, two: 'two')
[one, two]
end
This page:
http://chriszetter.com/blog/2012/11/02/keyword-arguments-in-ruby-2-dot-0/
says Keyword arguments in the method definition must be symbols given in the new-style hash syntax but then what appear to be symbols in the parameters of the method are then method variables in the returned Array.
Can symbols change 'type' without even being changed by a method? Or, in this case, is there a method I'm not seeing that's changing the type? And if the type doesn't matter, why does it appear to change? Or can symbols be referred to without a colon?
If I'm wrong about any of this, please feel free to correct me and let me know what actually IS going on! Thanks.
No, symbols cannot change type on their own, but when you're using one or two in your example, you are using variables with similar names, provided by Ruby based on your method definition, not the symbols themselves.
Consider a hash: when you have a hash a = { one: 1, two: '1234' } and you write a[:one] you don't get a symbol, but an appropriate value. So :one still is a symbol, but with [a[:one], a[:two]] you will get [1, '1234'] array, not [:one, :two].
There are no symbols here. one and two are parameters, parameters become local variable variables in the method body.
In
def foo(bar:, baz:)
bar and baz are no more symbols than they are in
def foo(bar, baz)
In the first case they are keyword parameters, in the second case they are positional parameters, other than that, there is no difference. In the parameter list, they are parameter placeholders, in the method body, they become local variables bound to arguments.

Usage of symbols and table of symbols

In many of the Rails methods, symbols are being passed as arguments. I'm not sure how some of those arguments are references to other methods. In other words, the symbol points to another method. I understand how a symbol like :something will always point to the same memory allocation, which is different from multiple instances of, say, "something". If I have a symbol :x and also defined a method x(), does it mean that these two are linked somehow?
A Ruby book describes the concept of a table of symbols:
A symbol is an identifier whose value is itself. This describes, in a broad sense, they way that symbols behave from the point of view of the Ruby programmer. But it doesn't tell you what symbols are literally from the point of view of the Ruby interpreter. A symbol is, in fact, a pointer into the symbol table. The symbol table is Ruby's internal list of known identifiers—such as variable and method names.
I stumbled upon how it refers to different methods or strings. Can someone help me understand this table of symbols and how it relates to symbols being used as method names?
Symbols by themselves are not connected with methods in any way. Certain methods can accept symbols to dynamically call other methods, using symbols as their names. Observe:
class Foo
def bar
"called bar"
end
def baz
"called bazzz"
end
def invoke m
send m
end
end
f = Foo.new
f.invoke :bar # => "called bar"
f.invoke :baz # => "called bazzz"
# since `invoke` just delegates execution to `send`, and `send` can accept strings as well
# we can pass a string here.
f.invoke 'baz' # => "called bazzz"
This is the same case as in
before_filter :init_session
validates_presence_of :first_name
And many others
Edit:
if I have a symbol :x and also defined a method x(), does it mean that these two are linked somehow?
No, they are not linked in any way. You can safely ignore that passage about symbol table. It's unnecessary implementation detail for you at the moment.
Symbol names and method names are not linked in any way. A symbol is most closely related to a string. The difference between a string and a symbol is that a symbol is a unique object for the entire Ruby interpreter whereas strings are always unique objects. To illustrate this, open up IRB:
irb
1.9.3-p362 :001 > "hello".object_id
=> 70162149682220
1.9.3-p362 :002 > "hello".object_id
=> 70162149699280
1.9.3-p362 :003 > :hello.object_id
=> 460328
1.9.3-p362 :004 > :hello.object_id
=> 460328
1.9.3-p362 :005 > "hello".to_sym.object_id
=> 460328
As you can see, two identical strings containing "hello" have different object ids, even though they contain the same contents. Symbols on the other hand, always have the same object id as long as the contents of the symbol are the same. You can see that converting the string "hello" to a symbol gives the same object id as the symbol :hello. Symbols are much more memory efficient to use, and equality comparison is much faster. The trade off is that a symbol is essentially a memory leak, because you can never remove one from memory once you define it.
As Sergio said, you can invoke methods using the send method, but send uses Ruby's robust reflection to execute methods by name at runtime, it has nothing inherently to do with symbols other than the method names are identified by a symbol.
EDIT: If you are curious about how this works, check out Ruby Metaprogramming to see the things you are able to do. To understand exactly how this works, however, you would need to look at the C source code of the Ruby language.
If you define symbol :x and also defined a method x() and print :x.class => Symbol , x.class => "Datatype of return field or if nothing is return then NilClass".
This Shows that there is no relation between symbol :x and method x().
Things done with Symbol can also be done with String in Ruby.
Symbols are used instead of string if u want one instance of string means you want one memory location for particular string ,obviously for performance benefit.
Internally Ruby saves Methods name as Symbol.
So its better to use Symbol when passing Methods names around like in case of attr_accessor and send but its not compulsory and you can use String otherwise.

Why is :key.hash != 'key'.hash in Ruby?

I'm learning Ruby right now for the Rhodes mobile application framework and came across this problem: Rhodes' HTTP client parses JSON responses into Ruby data structures, e.g.
puts #params # prints {"body"=>{"results"=>[]}}
Since the key "body" is a string here, my first attempt #params[:body] failed (is nil) and instead it must be #params['body']. I find this most unfortunate.
Can somebody explain the rationale why strings and symbols have different hashes, i.e. :body.hash != 'body'.hash in this case?
Symbols and strings serve two different purposes.
Strings are your good old familiar friends: mutable and garbage-collectable. Every time you use a string literal or #to_s method, a new string is created. You use strings to build HTML markup, output text to screen and whatnot.
Symbols, on the other hand, are different. Each symbol exists only in one instance and it exists always (i.e, it is not garbage-collected). Because of that you should make new symbols very carefully (String#to_sym and :'' literal). These properties make them a good candidate for naming things. For example, it's idiomatic to use symbols in macros like attr_reader :foo.
If you got your hash from an external source (you deserialized a JSON response, for example) and you want to use symbols to access its elements, then you can either use HashWithIndifferentAccess (as others pointed out), or call helper methods from ActiveSupport:
require 'active_support/core_ext'
h = {"body"=>{"results"=>[]}}
h.symbolize_keys # => {:body=>{"results"=>[]}}
h.stringify_keys # => {"body"=>{"results"=>[]}}
Note that it'll only touch top level and will not go into child hashes.
Symbols and Strings are never ==:
:foo == 'foo' # => false
That's a (very reasonable) design decision. After all, they have different classes, methods, one is mutable the other isn't, etc...
Because of that, it is mandatory that they are never eql?:
:foo.eql? 'foo' # => false
Two objects that are not eql? typically don't have the same hash, but even if they did, the Hash lookup uses hash and then eql?. So your question really was "why are symbols and strings not eql?".
Rails uses HashWithIndifferentAccess that accesses indifferently with strings or symbols.
In Rails, the params hash is actually a HashWithIndifferentAccess rather than a standard ruby Hash object. This allows you to use either strings like 'action' or symbols like :action to access the contents.
You will get the same results regardless of what you use, but keep in mind this only works on HashWithIndifferentAccess objects.
Copied from : Params hash keys as symbols vs strings

Ruby and :symbols

I have just started using Ruby and I am reading "Programming Ruby 1.9 - The Pragmatic Programmer's Guide". I came across something called symbols, but as a PHP developer I don't understand what they do and what they are good for.
Can anyone help me out with this?
It's useful to think of symbols in terms of "the thing called." In other words, :banana is referring to "the thing called banana." They're used extensively in Ruby, mostly as Hash (associative array) keys.
They really are similar to strings, but behind the scenes, very different. One key difference is that only one of a particular symbol exists in memory. So if you refer to :banana 10 times in your code, only one instance of :banana is created and they all refer to that one. This also implies they're immutable.
Symbols are similar to string literals in the sense that share the same memory space, but it is important to remark they are not string equivalents.
In Ruby, when you type "this" and "this" you're using two different memory locations; by using symbols you'll use only one name during the program execution. So if you type :this in several places in your program, you'll be using only one.
From Symbol doc:
Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program‘s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.
So, you basically use it where you want to treat a string as a constant.
For instance, it is very common to use it with the attr_accessor method, to define getter/setter for an attribute.
class Person
attr_accessor :name
end
p = Person.new
p.name= "Oscar"
But this would do the same:
class DontDoThis
attr_accessor( "name" )
end
ddt = DontDoThis.new
ddt.name= "Dont do it"
Think of a Symbol as a either:
A method name that you plan to use later
A constant / enumeration that you want to store and compare against
For example:
s = "FooBar"
length = s.send(:length)
>>> 6
#AboutRuby has a good answer, using the terms "the thing called".
:banana is referring to "the thing
called banana."
He notes that you can refer to :banana many times in the code and its the same object-- even in different scopes or off in some weird library. :banana is the thing called banana, whatever that might mean when you use it.
They are used as
keys to arrays, so you look up :banana you only have one entry. In most languages if these are Strings you run the risk of having multiple Strings in memory with the text "banana" and not having the code detect they are the same
method/proc names. Most people are familiar with how C distinguishes a method from its call with parentheses: my_method vs. my_method(). In Ruby, since parentheses are optional, these both indicate a call to that method. The symbol, however, is convenient to use as a standin for methods (even though there really is no relationship between a symbol and a method).
enums (and other constants). Since they don't change they exhibit many of the properties of these features from other languages.

Resources