Does attr_accessor require using symbols as variables in Ruby? - ruby

Every example of attr_accessors I've seen uses a symbol (:var) as the variable.
Is this a requirement of using attr_accessorand, if so, why? If not, why is it such a common practice?

Module#attr_accessor
attr_accessor(symbol, ...) → nil
attr_accessor(string, ...) → nil (newly introduced in Ruby 2.1)
Defines a named attribute for this module, where the name is symbol.id2name, creating an instance variable (#name) and a corresponding access method to read it. Also creates a method called name= to set the attribute. String arguments are converted to symbols.
Is this a requirement of using attr_accessor?
No, you are allowed with symbols as well as strings.
Read this - Understanding Ruby symbol as method call

While the current version of ruby (2.1) permits passing a string (as mentioned by #ArupRakshit), older versions of ruby did not (2.0 and prior). As such, any code that isn't relying on ruby 2.1 (and that would be almost everything) will need to pass symbols.
Aside for this, in most cases you'd want to be passing symbols anyhow, as they are atomic, have less overhead, and are semantically more in line with attribute definition than strings are.

Related

Are there any use-cases for Array#push (unshift) without argument?

I am surprised to know Ruby's Array#push (and Array#unshift) can be invoked without argument and they do nothing.
In my opinion raising ArgumentError seems to be more appropriate behavior when no argument is passed to these methods (just like append in Python).
Are there any use-cases for Array#push (Array#unshift) without argument?
The documentation clearly lists one mandatory parameter.
However, the Ruby Spec Suite shows an example of passing 0 arguments.
The MRI/YARV test suite also explicitly shows that passing 0 arguments should be possible, however there is a commented line that actually tests the opposite, namely that passing 0 arguments will raise an exception, and there is a comment which says that this feature was introduced in Ruby 1.8.
So, apparently, in Ruby 1.6 and earlier, there used to be one mandatory parameter, and Ruby 1.8 introduced the possibility of an arbitrary number of arguments. The only use-case I can think of is splatting a potentially empty array or nil without raising an error.

Using Ruby Symbols

First time I tried learning Ruby was 2 years ago, now I have started again. The reason I stopped was because I could not understand the Symbol class. And now I am at the same point again, completely lost in when and why you use Symbols. I have read the other posts on Stackoverflow as well as Googled for several explanations. But I do not understand it yet.
First I thought symbols was just a way to create some sort of "named constant" without having to go through the same process as in let say Java.
:all
instead of making a constant with an arbitrary value public static final String ALL = 8;
However it does not make much sense when you use it in e.g. attr_accessor :first_name etc.
Are Symbols just a lightweight String class? I am having problems understanding how I should interpret, when and how to use symbols both in my own classes and in frameworks.
In short, symbols are lightweight strings, but they also are immutable and non-garbage-collectable.
You should not use them as immutable strings in your data processing tasks (remember, once symbol is created, it can't be destroyed). You typically use symbols for naming things.
# typical use cases
# access hash value
user = User.find(params[:id])
# name something
attr_accessor :first_name
# set hash value in opts parameter
db.collection.update(query, update, multi: true, upsert: true)
Let's take first example, params[:id]. In a moderately big rails app there may be hundreds/thousands of those scattered around the codebase. If we accessed that value with a string, params["id"], that means new string allocation each time (and that string needs to be collected afterwards). In case of symbol, it's actually the same symbol everywhere. Less work for memory allocator, garbage collector and even you (: is faster to type than "")
If you have a simple one-word string that appears often in your code and you don't do something funky to it (interpolation, gsub, upcase, etc), then it's likely a good candidate to be a symbol.
However, does this apply only to text that is used as part of the actual program logic such as naming, not text that you get while actually running the program...such as text from the user/web etc?
I can not think of a single case where I'd want to turn data from user/web to symbol (except for parsing command-line options, maybe). Mainly because of the consequences (once created symbols live forever).
Also, many editors provide different coloring for symbols, to highlight them in the code. Take a look at this example
The O'Reilly Ruby Cookbook (p. 15) quotes Jim Weirich as saying:
If the contents (the sequence of characters) of the object are important, use a string.
If the identity of the object is important, use a symbol.
Symbols are generally used as hash keys, because it's the identity of the key that's important. Symbols are also required when passing messages using certain methods like Object#send.
A Ruby implementation typically has a table in which it stores the names of all classes, methods and variables. It refers to say a method name by the position in the table, avoiding expensive string comparisons. But you can use this table too and add values to it: symbols.
If you write code that uses strings as identifiers rather than for their textual content, consider symbols. If you write a method that expects an argument to be either 'male' or 'female', consider using :male and :female . Comparing two symbols for equality is faster than strings (that's why symbols make good hash keys).
Symbols are used for naming things in the language: the names of classes, the names of methods etc.
These are very like strings, except they can never be garbage collected, and testing for equality is optimised to be very quick.
The Java implementation has a very similar thing, except that it is not available for runtime use. What I mean is, when you write java code like obj.someMethod(4), the string 'someMethod' is converted by the compiler into a symbol which is embedded in a lookup table in the .class file. These symbols are like 'special' strings which are not garbage collected, and which are very fast to compare for equality. This is almost identical to Ruby, except that Ruby allows you to create new symbols at runtime, whereas Java only allows it at compile time.
This is just like creating new methods -- Java allows it at compile time; Ruby allows it at runtime.
After ruby version 2.2 symbol GC was removed, so now mortal symbols i.e when we convert string to symbol ("mortal".to_sym) gets cleaned up from memory.
check this out:
require 'objspace'
ObjectSpace.count_symbols
{
:mortal_dynamic_symbol=>3,
:immortal_dynamic_symbol=>5,
:immortal_static_symbol=>3663,
:immortal_symbol=>3668
}
source: https://www.rubyguides.com/2018/02/ruby-symbols/

Why aren't the arguments to File.new symbols instead of strings?

I was wondering why the people who wrote the File library decided to make the arguments that determine what mode the file is opened in strings instead of symbols.
For example, this is how it is now:
f = File.new('file', 'rw')
But wouldn't it be a better design to do
f = File.new('file', :rw)
or even
f = File.new(:file, :rw)
for example? This seems to be the perfect place to use them since the argument definitely doesn't need to be mutable.
I am interested in knowing why it came out this way.
Update: I just got done reading a related question about symbols vs. strings, and I think the consensus was that symbols are just not as well known as strings, and everyone is used to using strings to index hash tables anyway. However, I don't think it would be valid for the designers of Ruby's standard library to plead ignorance on the subject of symbols, so I don't think that's the reason.
I'm no expert in the history of ruby, but you really have three options when you want parameters to a method: strings, symbols, and static classes.
For example, exception handling. Each exception is actually a type of class Exception.
ArgumentError.is_a? Class
=> True
So you could have each permission for the stream be it's own class. But that would require even more classes to be generated for the system.
The thing about symbols is they are never deleted. Every symbol you generate is preserved indefinitely; it's why using the method '.to_sym' lightly is discouraged. It leads to memory leaks.
Strings are just easier to manipulate. If you got the input mode from the user, you would need a '.to_sym' somewhere in your code, or at the very least, a large switch statement. With a string, you can just pass the user input directly to the method (if you were so trusting, of course).
Also, in C, you pass a character to the file i/o method. There are no Chars in ruby, just strings. Seeing as how ruby is built on C, that could be where it comes from.
It is simply a relic from previous languages.

What does the : mean in rails before a variable name?

For example, : symbol - I'm trying to work out what the : means, and how it differs, say, for example, from # and also from no symbol whatsoever.
If there's a guide that would be really helpful!
It's a symbol, which is a Ruby language construct.
Symbols are similar to strings, but this blog post explains the details.
# means an instance variable on the class: it's basically a variable that's shared among all methods on an instance of a class. It has no relation to :.
: denotes that you are using a symbol.
# is an instance variable - basically a variable that is set once and can be used through a ruby process until it is done.
Plain old variable_name is a local variable and that variable is only good for as long as that method is called.
As for guides, you should read up on ruby basics or take a look at the something like this
# is an ivar
: is an symbol (think it like a COSTANT in C, but without any numerical value)
http://rubylearning.com/satishtalim/ruby_symbols.html and http://www.troubleshooters.com/codecorn/ruby/symbols.htm are 2 well written guides (second one might be a bit old, but most of it applies in Ruby 1.9 too).
You might also want to check the official documentation on Symbol at http://www.ruby-doc.org/core/classes/Symbol.html

Ruby's :yields:

I was looking through some tab-completions that were automatically set up for my editor, and I found one where y was mapped to:
:yields: arguments
What is this syntax called, when, where, how and for what is this used?
This is one of the many directives supported by the RDoc documentation tool. It is used to document the arguments that get passed to a block.

Resources