Ruby is one of the popular programming languages which was developed by Yukihiro Matsumoto in the mid-1990s. Ruby is a general-purpose language and is easy to learn. So, today we will be talking about the top 14 most asked questions about Ruby.
So, let’s get started.
Answer:
You can use
expression.case
<code><span class="kwd">case</span><span class="pln"> x
</span><span class="kwd">when</span> <span class="lit">1.</span><span class="pun">.</span><span class="lit">5</span>
<span class="str">"It's between 1 and 5"</span>
<span class="kwd">when</span> <span class="lit">6</span>
<span class="str">"It's 6"</span>
<span class="kwd">when</span> <span class="str">"foo"</span><span class="pun">,</span> <span class="str">"bar"</span>
<span class="str">"It's either foo or bar"</span>
<span class="kwd">when</span> <span class="typ">String</span>
<span class="str">"You passed a string"</span>
<span class="kwd">else</span>
<span class="str">"You gave me #{x} -- I have no idea what to do with that."</span>
<span class="kwd">end</span></code>
Ruby compares the object in the
when
clause with the object in the case
clause using the ===
operator. For example, 1..5 === x
, and not x === 1..5
.This allows for sophisticated
when
clauses as seen above. Ranges, classes, and all sorts of things can be tested for rather than just equality.Unlike
switch
statements in many other languages, Ruby’s case
does not have fall-through, so there is no need to end each when
with a break
. You can also specify multiple matches in a single when
clause like when "foo", "bar"
.Alternative Answer:
case...when
behaves a bit unexpectedly when handling classes. This is due to the fact that it uses the ===
operator.That operator works as expected with literals, but not with classes:
<code><span class="lit">1</span> <span class="pun">===</span> <span class="lit">1</span> <span class="com"># => true</span>
<span class="typ">Fixnum</span> <span class="pun">===</span> <span class="typ">Fixnum</span> <span class="com"># => false</span></code>
This means that if you want to do a
case ... when
over an object’s class, this will not work:<code><span class="pln">obj </span><span class="pun">=</span> <span class="str">'hello'</span>
<span class="kwd">case</span><span class="pln"> obj</span><span class="pun">.</span><span class="kwd">class</span>
<span class="kwd">when</span> <span class="typ">String</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is a string'</span><span class="pun">)</span>
<span class="kwd">when</span> <span class="typ">Fixnum</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is a number'</span><span class="pun">)</span>
<span class="kwd">else</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is not a string or number'</span><span class="pun">)</span>
<span class="kwd">end</span></code>
Will print “It is not a string or number”.
Fortunately, this is easily solved. The
===
operator has been defined so that it returns true
if you use it with a class and supply an instance of that class as the second operand:<code><span class="typ">Fixnum</span> <span class="pun">===</span> <span class="lit">1</span> <span class="com"># => true</span></code>
In short, the code above can be fixed by removing the
.class
:<code><span class="pln">obj </span><span class="pun">=</span> <span class="str">'hello'</span>
<span class="kwd">case</span><span class="pln"> obj </span><span class="com"># was case obj.class</span>
<span class="kwd">when</span> <span class="typ">String</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is a string'</span><span class="pun">)</span>
<span class="kwd">when</span> <span class="typ">Fixnum</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is a number'</span><span class="pun">)</span>
<span class="kwd">else</span><span class="pln">
print</span><span class="pun">(</span><span class="str">'It is not a string or number'</span><span class="pun">)</span>
<span class="kwd">end</span></code>
Answer:
You can use
:include?
<code><span class="pun">>></span> <span class="pun">[</span><span class="str">'Cat'</span><span class="pun">,</span> <span class="str">'Dog'</span><span class="pun">,</span> <span class="str">'Bird'</span><span class="pun">].</span><span class="pln">include</span><span class="pun">?</span> <span class="str">'Dog'</span>
<span class="pun">=></span> <span class="kwd">true</span></code>
Alternative Answer:
There is an
method in in?
ActiveSupport
(part of Rails) since v3.1. So within Rails, or if you require 'active_support'
, you can write:<code><span class="str">'Unicorn'</span><span class="pun">.</span><span class="kwd">in</span><span class="pun">?([</span><span class="str">'Cat'</span><span class="pun">,</span> <span class="str">'Dog'</span><span class="pun">,</span> <span class="str">'Bird'</span><span class="pun">])</span> <span class="com"># => false</span></code>
On the other hand, there is no
in
operator or #in
? method in Ruby itself, even though it has been proposed before, in particular by Yusuke Endoh a top-notch member of ruby-core.On the other hand, the reverse method
exists, for all include?
Enumerable
s including Array
, Hash
, Set
, Range
:<code><span class="pun">[</span><span class="str">'Cat'</span><span class="pun">,</span> <span class="str">'Dog'</span><span class="pun">,</span> <span class="str">'Bird'</span><span class="pun">].</span><span class="pln">include</span><span class="pun">?(</span><span class="str">'Unicorn'</span><span class="pun">)</span> <span class="com"># => false</span></code>
Note that if you have many values in your array, they will all be checked one after the other (i.e.
O(n)
), while that lookup for a hash will be constant time (i.e O(1)
). So if your array is constant, for example, it is a good idea to use a Set instead. E.g:<code><span class="pln">require </span><span class="str">'set'</span><span class="pln">
ALLOWED_METHODS </span><span class="pun">=</span> <span class="typ">Set</span><span class="pun">[:</span><span class="pln">to_s</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">to_i</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">upcase</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">downcase
</span><span class="com"># etc</span>
<span class="pun">]</span>
<span class="kwd">def</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">what</span><span class="pun">)</span><span class="pln">
raise </span><span class="str">"Not allowed"</span> <span class="kwd">unless</span><span class="pln"> ALLOWED_METHODS</span><span class="pun">.</span><span class="pln">include</span><span class="pun">?(</span><span class="pln">what</span><span class="pun">.</span><span class="pln">to_sym</span><span class="pun">)</span><span class="pln">
bar</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="pln">what</span><span class="pun">)</span>
<span class="kwd">end</span></code>
A quick test reveals that calling
include?
on a 10 element Set
is about 3.5x faster than calling it on the equivalent Array
(if the element is not found).But, be wary when using
include?
on a Range
, there are subtleties, so refer to the doc and compare with cover?
Answer:
Ruby has a few methods for changing the case of strings. To convert to lowercase, use
downcase
:<code><span class="str">"hello James!"</span><span class="pun">.</span><span class="pln">downcase </span><span class="com">#=> "hello james!"</span></code>
Similarly,
upcase
capitalizes every letter and capitalize
capitalizes the first letter of the string but lowercases the rest:<code><span class="str">"hello James!"</span><span class="pun">.</span><span class="pln">upcase </span><span class="com">#=> "HELLO JAMES!"</span>
<span class="str">"hello James!"</span><span class="pun">.</span><span class="pln">capitalize </span><span class="com">#=> "Hello james!"</span>
<span class="str">"hello James!"</span><span class="pun">.</span><span class="pln">titleize </span><span class="com">#=> "Hello James!"</span></code>
If you want to modify a string in place, you can add an exclamation point to any of those methods:
<code><span class="pln">string </span><span class="pun">=</span> <span class="str">"hello James!"</span><span class="pln">
string</span><span class="pun">.</span><span class="pln">downcase</span><span class="pun">!</span><span class="pln">
string </span><span class="com">#=> "hello james!"</span></code>
Alternative Answer:
You can find out all the methods available on a String by opening irb and running:
<code><span class="str">"MyString"</span><span class="pun">.</span><span class="pln">methods</span><span class="pun">.</span><span class="pln">sort</span></code>
And for a list of the methods available for strings in particular:
<code><span class="str">"MyString"</span><span class="pun">.</span><span class="pln">own_methods</span><span class="pun">.</span><span class="pln">sort</span></code>
Answer:
Options and dependencies need to be inside arrays:
<code><span class="pln">namespace </span><span class="pun">:</span><span class="pln">thing </span><span class="kwd">do</span><span class="pln">
desc </span><span class="str">"it does a thing"</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">work</span><span class="pun">,</span> <span class="pun">[:</span><span class="pln">option</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">]</span> <span class="kwd">do</span> <span class="pun">|</span><span class="pln">task</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">|</span><span class="pln">
puts </span><span class="str">"work"</span><span class="pun">,</span><span class="pln"> args
</span><span class="kwd">end</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">another</span><span class="pun">,</span> <span class="pun">[:</span><span class="pln">option</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">]</span> <span class="kwd">do</span> <span class="pun">|</span><span class="pln">task</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">|</span><span class="pln">
puts </span><span class="str">"another #{args}"</span>
<span class="typ">Rake</span><span class="pun">::</span><span class="typ">Task</span><span class="pun">[</span><span class="str">"thing:work"</span><span class="pun">].</span><span class="pln">invoke</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[:</span><span class="pln">option</span><span class="pun">],</span><span class="pln"> args</span><span class="pun">[:</span><span class="pln">foo</span><span class="pun">],</span><span class="pln"> args</span><span class="pun">[:</span><span class="pln">bar</span><span class="pun">])</span>
<span class="com"># or splat the args</span>
<span class="com"># Rake::Task["thing:work"].invoke(*args)</span>
<span class="kwd">end</span>
<span class="kwd">end</span></code>
Then
<code><span class="pln">rake thing</span><span class="pun">:</span><span class="pln">work</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">]</span>
<span class="pun">=></span><span class="pln"> work</span><span class="pun">:</span> <span class="pun">{:</span><span class="pln">option</span><span class="pun">=></span><span class="str">"1"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">=></span><span class="str">"2"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">=></span><span class="str">"3"</span><span class="pun">}</span><span class="pln">
rake thing</span><span class="pun">:</span><span class="pln">another</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">]</span>
<span class="pun">=></span><span class="pln"> another </span><span class="pun">{:</span><span class="pln">option</span><span class="pun">=></span><span class="str">"1"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">=></span><span class="str">"2"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">=></span><span class="str">"3"</span><span class="pun">}</span>
<span class="pun">=></span><span class="pln"> work</span><span class="pun">:</span> <span class="pun">{:</span><span class="pln">option</span><span class="pun">=></span><span class="str">"1"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">=></span><span class="str">"2"</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">=></span><span class="str">"3"</span><span class="pun">}</span></code>
NOTE: variable
task
is the task object, not very helpful unless you know/care about Rake internals.Rails Note: If running the task from rails, it is best to preload the environment by adding
=> [:environment]
which is a way to set up dependent tasks.<code><span class="pln"> task </span><span class="pun">:</span><span class="pln">work</span><span class="pun">,</span> <span class="pun">[:</span><span class="pln">option</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">foo</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">bar</span><span class="pun">]</span> <span class="pun">=></span> <span class="pun">[:</span><span class="pln">environment</span><span class="pun">]</span> <span class="kwd">do</span> <span class="pun">|</span><span class="pln">task</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">|</span><span class="pln">
puts </span><span class="str">"work"</span><span class="pun">,</span><span class="pln"> args
</span><span class="kwd">end</span></code>
Alternative Answer:
You can specify formal arguments in rake by adding symbol arguments to the task call. For example:
<code><span class="pln">require </span><span class="str">'rake'</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">my_task</span><span class="pun">,</span> <span class="pun">[:</span><span class="pln">arg1</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">arg2</span><span class="pun">]</span> <span class="kwd">do</span> <span class="pun">|</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">|</span><span class="pln">
puts </span><span class="str">"Args were: #{args} of class #{args.class}"</span><span class="pln">
puts </span><span class="str">"arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"</span><span class="pln">
puts </span><span class="str">"arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"</span>
<span class="kwd">end</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">invoke_my_task </span><span class="kwd">do</span>
<span class="typ">Rake</span><span class="pun">.</span><span class="pln">application</span><span class="pun">.</span><span class="pln">invoke_task</span><span class="pun">(</span><span class="str">"my_task[1, 2]"</span><span class="pun">)</span>
<span class="kwd">end</span>
<span class="com"># or if you prefer this syntax...</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">invoke_my_task_2 </span><span class="kwd">do</span>
<span class="typ">Rake</span><span class="pun">::</span><span class="typ">Task</span><span class="pun">[:</span><span class="pln">my_task</span><span class="pun">].</span><span class="pln">invoke</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span> <span class="lit">4</span><span class="pun">)</span>
<span class="kwd">end</span>
<span class="com"># a task with prerequisites passes its </span>
<span class="com"># arguments to it prerequisites</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">with_prerequisite</span><span class="pun">,</span> <span class="pun">[:</span><span class="pln">arg1</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">arg2</span><span class="pun">]</span> <span class="pun">=></span> <span class="pun">:</span><span class="pln">my_task </span><span class="com">#<- name of prerequisite task</span>
<span class="com"># to specify default values, </span>
<span class="com"># we take advantage of args being a Rake::TaskArguments object</span><span class="pln">
task </span><span class="pun">:</span><span class="pln">with_defaults</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">arg1</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">arg2 </span><span class="kwd">do</span> <span class="pun">|</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">|</span><span class="pln">
args</span><span class="pun">.</span><span class="pln">with_defaults</span><span class="pun">(:</span><span class="pln">arg1 </span><span class="pun">=></span> <span class="pun">:</span><span class="pln">default_1</span><span class="pun">,</span> <span class="pun">:</span><span class="pln">arg2 </span><span class="pun">=></span> <span class="pun">:</span><span class="pln">default_2</span><span class="pun">)</span><span class="pln">
puts </span><span class="str">"Args with defaults were: #{args}"</span>
<span class="kwd">end</span></code>
Then, from the command line:
> rake my_task[1,false]
Args were: {:arg1=>"1", :arg2=>"false"} of class Rake::TaskArguments
arg1 was: '1' of class String
arg2 was: 'false' of class String
> rake "my_task[1, 2]"
Args were: {:arg1=>"1", :arg2=>"2"}
> rake invoke_my_task
Args were: {:arg1=>"1", :arg2=>"2"}
> rake invoke_my_task_2
Args were: {:arg1=>3, :arg2=>4}
> rake with_prerequisite[5,6]
Args were: {:arg1=>"5", :arg2=>"6"}
> rake with_defaults
Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2}
> rake with_defaults['x','y']
Args with defaults were: {:arg1=>"x", :arg2=>"y"}
As demonstrated in the second example, if you want to use spaces, the
quotes around the target name are necessary to keep the shell from
splitting up the arguments at the space.
Looking at the code in rake.rb, it appears that rake does not parse task strings to extract arguments for prerequisites, so you can’t do
task :t1 => "dep[1,2]"
. The only way to specify different arguments for a prerequisite would be to invoke it explicitly within the dependent task action, as in :invoke_my_task
and :invoke_my_task_2
.Note that some shells (like zsh) require you to escape the brackets:
rake my_task\['arg1'\]
Answer:
First, note that when Ruby calls out to a shell, it typically calls
/bin/sh
, not Bash. Some Bash syntax is not supported by /bin/sh
on all systems.Here are ways to execute a shell script:
<code><span class="pln">cmd </span><span class="pun">=</span> <span class="str">"echo 'hi'"</span> <span class="com"># Sample string that can be used</span></code>
Kernel#`
, commonly called backticks – `cmd`
This is like many other languages, including Bash, PHP, and Perl. It returns the result (i.e. standard output) of the shell command.<code><span class="kwd">value</span> <span class="pun">=</span> <span class="str">`echo 'hi'`</span>
<span class="kwd">value</span> <span class="pun">=</span> <span class="str">`#{cmd}`</span></code>
%x( cmd )
Following the x
character is a delimiter, which can be any character. If the delimiter is one of the characters (
, [
, {
, or <
, the literal consists of the characters up to the matching closing delimiter, taking account of nested delimiter pairs. For all other delimiters, the literal comprises the characters up to the next #{ ... }
is allowed. It returns the result (i.e. standard output) of the shell command, just like the backticks.<code><span class="kwd">value</span> <span class="pun">=</span> <span class="pun">%</span><span class="pln">x</span><span class="pun">(</span><span class="pln"> echo </span><span class="str">'hi'</span> <span class="pun">)</span>
<span class="kwd">value</span> <span class="pun">=</span> <span class="pun">%</span><span class="pln">x</span><span class="pun">[</span> <span class="com">#{cmd} ]</span></code>
Kernel#system
Executes the given command in a subshell. Returns true
if the command was found and run successfully, false
otherwise. Docs: http://ruby-doc.org/core/Kernel.html#method-i-system<code><span class="pln">wasGood </span><span class="pun">=</span><span class="pln"> system</span><span class="pun">(</span> <span class="str">"echo 'hi'"</span> <span class="pun">)</span><span class="pln">
wasGood </span><span class="pun">=</span><span class="pln"> system</span><span class="pun">(</span><span class="pln"> cmd </span><span class="pun">)</span></code>
Kernel#exec
Replaces the current process by running the <code><span class="kwd">exec</span><span class="pun">(</span> <span class="str">"echo 'hi'"</span> <span class="pun">)</span>
<span class="kwd">exec</span><span class="pun">(</span><span class="pln"> cmd </span><span class="pun">)</span> <span class="com"># Note: this will never be reached because of the line above</span></code>
Here’s some extra advice:
$?
, which is the same as $CHILD_STATUS
, accesses the status of the last system executed command if you use the backticks, system()
or %x{}
. You can then access the exitstatus
and pid
properties:<code><span class="pln">$</span><span class="pun">?.</span><span class="pln">exitstatus</span></code>
Alternative Answer:
Using the
%x
literal, which makes it easy (and readable!) to use quotes in a command, like so:<code><span class="pln">directorylist </span><span class="pun">=</span> <span class="pun">%</span><span class="pln">x</span><span class="pun">[</span><span class="pln">find </span><span class="pun">.</span> <span class="pun">-</span><span class="pln">name </span><span class="str">'*test.rb'</span> <span class="pun">|</span><span class="pln"> sort</span><span class="pun">]</span></code>
Which, in this case, will populate file list with all test files under the current directory, which you can process as expected:
<code><span class="pln">directorylist</span><span class="pun">.</span><span class="pln">each </span><span class="kwd">do</span> <span class="pun">|</span><span class="pln">filename</span><span class="pun">|</span><span class="pln">
filename</span><span class="pun">.</span><span class="pln">chomp</span><span class="pun">!</span>
<span class="com"># work with file</span>
<span class="kwd">end</span></code>
Answer:
You just add the following line to your local
~/.gemrc
file (it is in your home folder):<code><span class="pln">gem</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">document</span></code>
or you can add this line to the global
gemrc
config file.Here is how to find it (in Linux):
<code><span class="pln">strace gem source </span><span class="lit">2</span><span class="pun">>&</span><span class="lit">1</span> <span class="pun">|</span><span class="pln"> grep gemrc</span></code>
Alternative Answers:
1) From RVM’s documentation:
Just add this line to your
~/.gemrc
or /etc/gemrc
:<code><span class="pln">gem</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">rdoc </span><span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">ri </span></code>
Note: The original answer was:
<code><span class="pln">install</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">rdoc </span><span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">ri
update</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">rdoc </span><span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">ri </span></code>
This is no longer valid; the RVM docs have since been updated, thus the current answer to only include the
gem
directive is the correct one.2) Note that
--no-ri
and --no-rdoc
have been deprecated according to the new guides. The recommended way is to use --no-document
in ~/.gemrc
or /etc/gemrc
.<code><span class="pln">install</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">document
update</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">document</span></code>
or
<code><span class="pln">gem</span><span class="pun">:</span> <span class="pun">--</span><span class="pln">no</span><span class="pun">-</span><span class="pln">document</span></code>
Answer:
Let’s say you have a class
Person
.<code><span class="kwd">class</span> <span class="typ">Person</span>
<span class="kwd">end</span><span class="pln">
person </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">.</span><span class="pln">new
person</span><span class="pun">.</span><span class="pln">name </span><span class="com"># => no method error</span></code>
Obviously we never defined method
name
. Let’s do that.<code><span class="kwd">class</span> <span class="typ">Person</span>
<span class="kwd">def</span><span class="pln"> name
</span><span class="lit">@name</span> <span class="com"># simply returning an instance variable @name</span>
<span class="kwd">end</span>
<span class="kwd">end</span><span class="pln">
person </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">.</span><span class="pln">new
person</span><span class="pun">.</span><span class="pln">name </span><span class="com"># => nil</span><span class="pln">
person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span> <span class="str">"Dennis"</span> <span class="com"># => no method error</span></code>
We can read the name, but that doesn’t mean we can assign the name. Those are two different methods. The former is called reader and the latter is called writer. We didn’t create the writer yet so let’s do that.
<code><span class="kwd">class</span> <span class="typ">Person</span>
<span class="kwd">def</span><span class="pln"> name
</span><span class="lit">@name</span>
<span class="kwd">end</span>
<span class="kwd">def</span><span class="pln"> name</span><span class="pun">=(</span><span class="pln">str</span><span class="pun">)</span>
<span class="lit">@name</span> <span class="pun">=</span><span class="pln"> str
</span><span class="kwd">end</span>
<span class="kwd">end</span><span class="pln">
person </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">.</span><span class="pln">new
person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span> <span class="str">'Dennis'</span><span class="pln">
person</span><span class="pun">.</span><span class="pln">name </span><span class="com"># => "Dennis"</span></code>
Now we can write and read instance variable
@name
using reader and writer methods. Except, this is done so frequently, why waste time writing these methods every time? We can do it easier.<code><span class="kwd">class</span> <span class="typ">Person</span><span class="pln">
attr_reader </span><span class="pun">:</span><span class="pln">name
attr_writer </span><span class="pun">:</span><span class="pln">name
</span><span class="kwd">end</span></code>
Even this can get repetitive. When you want both reader and writer just use accessor!
<code><span class="kwd">class</span> <span class="typ">Person</span><span class="pln">
attr_accessor </span><span class="pun">:</span><span class="pln">name
</span><span class="kwd">end</span><span class="pln">
person </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">.</span><span class="pln">new
person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span> <span class="str">"Dennis"</span><span class="pln">
person</span><span class="pun">.</span><span class="pln">name </span><span class="com"># => "Dennis"</span></code>
Works the same way! And guess what: the instance variable
@name
in our person object will be set just like when we did it manually, so you can use it in other methods.<code><span class="kwd">class</span> <span class="typ">Person</span><span class="pln">
attr_accessor </span><span class="pun">:</span><span class="pln">name
</span><span class="kwd">def</span><span class="pln"> greeting
</span><span class="str">"Hello #{@name}"</span>
<span class="kwd">end</span>
<span class="kwd">end</span><span class="pln">
person </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">.</span><span class="pln">new
person</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span> <span class="str">"Dennis"</span><span class="pln">
person</span><span class="pun">.</span><span class="pln">greeting </span><span class="com"># => "Hello Dennis"</span></code>
Alternative Answer:
attr_accessor is just a method.
The trick is that
class
is not a definition in Ruby (it is “just a definition” in languages like C++ and Java), but it is an expression that evaluates. It is during this evaluation when the attr_accessor
method is invoked which in turn modifies the current class – remember the implicit receiver: self.attr_accessor
, where self
is the “open” class object at this point.The need for
attr_accessor
, is, well:x.y
form as is common in say, Java or even Python. In Ruby y
is always taken as a message to send (or “method to call”). Thus the attr_*
methods create wrappers which proxy the instance @variable
access through dynamically created methods.Answer:
Use
StandardError
instead for general exception catching. When the original exception is re-raised (e.g. when rescuing to log the exception only), rescuing Exception
is probably okay.Exception
is the root of Ruby’s exception hierarchy, so when you rescue Exception
you rescue from everything, including subclasses such as SyntaxError
, LoadError
, and Interrupt
.Rescuing
Interrupt
prevents the user from using CTRLC to exit the program.Rescuing
SignalException
prevents the program from responding correctly to signals. It will be unkillable except by kill -9
.Rescuing
SyntaxError
means that eval
s that fail will do so silently.All of these can be shown by running this program, and trying to CTRLC or
kill
it:<code><span class="pln">loop </span><span class="kwd">do</span>
<span class="kwd">begin</span><span class="pln">
sleep </span><span class="lit">1</span><span class="pln">
eval </span><span class="str">"djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"</span>
<span class="kwd">rescue</span> <span class="typ">Exception</span><span class="pln">
puts </span><span class="str">"I refuse to fail or be stopped!"</span>
<span class="kwd">end</span>
<span class="kwd">end</span></code>
Rescuing from
Exception
isn’t even the default. Doing<code><span class="kwd">begin</span>
<span class="com"># iceberg!</span>
<span class="kwd">rescue</span>
<span class="com"># lifeboats</span>
<span class="kwd">end</span></code>
does not rescue from
Exception
, it rescues from StandardError
. You should generally specify something more specific than the default StandardError
, but rescuing from Exception
broadens the scope rather than narrowing it, and can have catastrophic results and make bug-hunting extremely difficult.If you have a situation where you do want to rescue from
StandardError
and you need a variable with the exception, you can use this form:<code><span class="kwd">begin</span>
<span class="com"># iceberg!</span>
<span class="kwd">rescue</span> <span class="pun">=></span><span class="pln"> e
</span><span class="com"># lifeboats</span>
<span class="kwd">end</span></code>
which is equivalent to:
<code><span class="kwd">begin</span>
<span class="com"># iceberg!</span>
<span class="kwd">rescue</span> <span class="typ">StandardError</span> <span class="pun">=></span><span class="pln"> e
</span><span class="com"># lifeboats</span>
<span class="kwd">end</span></code>
One of the few common cases where it’s sane to rescue from
Exception
is for logging/reporting purposes, in which case you should immediately re-raise the exception:<code><span class="kwd">begin</span>
<span class="com"># iceberg?</span>
<span class="kwd">rescue</span> <span class="typ">Exception</span> <span class="pun">=></span><span class="pln"> e
</span><span class="com"># do some logging</span><span class="pln">
raise </span><span class="com"># not enough lifeboats ;)</span>
<span class="kwd">end</span></code>
Alternative Answer:
The real rule is: Don’t throw away exceptions. The objectivity of the author of your quote is questionable, as evidenced by the fact that it ends with
or I will stab you
Of course, be aware that signals (by default) throw exceptions, and normally long-running processes are terminated through a signal, so
catching Exception and not terminating on signal exceptions will make
your program very hard to stop. So don’t do this:
<code><span class="com">#! /usr/bin/ruby</span>
<span class="kwd">while</span> <span class="kwd">true</span> <span class="kwd">do</span>
<span class="kwd">begin</span><span class="pln">
line </span><span class="pun">=</span><span class="pln"> STDIN</span><span class="pun">.</span><span class="pln">gets
</span><span class="com"># heavy processing</span>
<span class="kwd">rescue</span> <span class="typ">Exception</span> <span class="pun">=></span><span class="pln"> e
puts </span><span class="str">"caught exception #{e}! ohnoes!"</span>
<span class="kwd">end</span>
<span class="kwd">end</span></code>
No, really, don’t do it. Don’t even run that to see if it works.
However, say you have a threaded server and you want all exceptions to not:
thread.abort_on_exception = true
).Then this is perfectly acceptable in your connection handling thread:
<code><span class="kwd">begin</span>
<span class="com"># do stuff</span>
<span class="kwd">rescue</span> <span class="typ">Exception</span> <span class="pun">=></span><span class="pln"> e
myLogger</span><span class="pun">.</span><span class="pln">error</span><span class="pun">(</span><span class="str">"uncaught #{e} exception while handling connection: #{e.message}"</span><span class="pun">)</span><span class="pln">
myLogger</span><span class="pun">.</span><span class="pln">error</span><span class="pun">(</span><span class="str">"Stack trace: #{backtrace.map {|l| "</span> <span class="com">#{l}\n"}.join}")</span>
<span class="kwd">end</span></code>
The above works out to a variation of Ruby’s default exception handler, with the advantage that it doesn’t also kill your program. Rails does this in its request handler.
Signal exceptions are raised in the main thread. Background threads won’t get them, so there is no point in trying to catch them there.
This is particularly useful in a production environment, where you do not want your program to simply stop whenever something goes wrong. Then
you can take the stack dumps in your logs and add to your code to deal with specific exception further down the call chain and in a more graceful manner.
Note also that there is another Ruby idiom which has much the same effect:
<code><span class="pln">a </span><span class="pun">=</span><span class="pln"> do_something </span><span class="kwd">rescue</span> <span class="str">"something else"</span></code>
In this line, if
do_something
raises an exception, it is caught by Ruby, thrown away, and a
is assigned "something else"
.Generally, don’t do that, except in special cases where you know you don’t need to worry. One example:
<code><span class="pln">debugger </span><span class="kwd">rescue</span> <span class="kwd">nil</span></code>
The
debugger
function is a rather nice way to set a breakpoint in your code, but if running outside a debugger, and Rails, it raises an exception. Now theoretically you shouldn’t be leaving debug code lying around in your program but you might want to keep it there for a while for some reason, but not continually run your debugger.Note:
pgrep ruby
, or ps | grep ruby
, look for your offending program’s PID, and then run kill -9 <PID>
.<code><span class="pun">%</span><span class="pln">W</span><span class="pun">/</span><span class="pln">INT QUIT TERM</span><span class="pun">/.</span><span class="pln">each </span><span class="pun">{</span> <span class="pun">|</span><span class="pln">sig</span><span class="pun">|</span><span class="pln"> trap sig</span><span class="pun">,</span><span class="str">"SYSTEM_DEFAULT"</span> <span class="pun">}</span></code>
This causes the program to respond to the normal termination signals by immediately terminating, bypassing exception handlers, with no cleanup. So it could cause data loss or similar. Be careful!
<code><span class="kwd">begin</span><span class="pln">
do_something
</span><span class="kwd">rescue</span> <span class="typ">Exception</span> <span class="pun">=></span><span class="pln"> e
critical_cleanup
raise
</span><span class="kwd">end</span></code>
you can actually do this:
<code><span class="kwd">begin</span><span class="pln">
do_something
</span><span class="kwd">ensure</span><span class="pln">
critical_cleanup
</span><span class="kwd">end</span></code>
In the second case,
critical cleanup
will be called every time, whether or not an exception is thrown.Answer:
Use the
-v
flag:<code><span class="pln">$ gem install fog </span><span class="pun">-</span><span class="pln">v </span><span class="lit">1.8</span></code>
Alternative Answer:
Use the
--version
parameter (shortcut -v):<code><span class="pln">$ gem install rails </span><span class="pun">-</span><span class="pln">v </span><span class="lit">0.14</span><span class="pun">.</span><span class="lit">1</span></code>
You can also use version comparators like
>=
or ~>
<code><span class="pln">$ gem install rails </span><span class="pun">-</span><span class="pln">v </span><span class="str">'~> 0.14.0'</span></code>
Or with newer versions of gem even:
<code><span class="pln">$ gem install rails</span><span class="pun">:</span><span class="lit">0.14</span><span class="pun">.</span><span class="lit">4</span><span class="pln"> rubyzip</span><span class="pun">:</span><span class="str">'< 1'</span>
<span class="pun">…</span>
<span class="typ">Successfully</span><span class="pln"> installed rails</span><span class="pun">-</span><span class="lit">0.14</span><span class="pun">.</span><span class="lit">4</span>
<span class="typ">Successfully</span><span class="pln"> installed rubyzip</span><span class="pun">-</span><span class="lit">0.9</span><span class="pun">.</span><span class="lit">9</span></code>
class << self
do in Ruby?Answer:
First, the
class << foo
syntax opens up foo
‘s singleton class (eigenclass). This allows you to specialize the behavior of methods called on that specific object.<code><span class="pln">a </span><span class="pun">=</span> <span class="str">'foo'</span>
<span class="kwd">class</span> <span class="pun"><<</span><span class="pln"> a
</span><span class="kwd">def</span><span class="pln"> inspect
</span><span class="str">'"bar"'</span>
<span class="kwd">end</span>
<span class="kwd">end</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">inspect </span><span class="com"># => "bar"</span><span class="pln">
a </span><span class="pun">=</span> <span class="str">'foo'</span> <span class="com"># new object, new singleton class</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">inspect </span><span class="com"># => "foo"</span></code>
Now, to answer the question:
class << self
opens up self
‘s singleton class, so that methods can be redefined for the current self
object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module (“static”) methods:<code><span class="kwd">class</span> <span class="typ">String</span>
<span class="kwd">class</span> <span class="pun"><<</span> <span class="kwd">self</span>
<span class="kwd">def</span><span class="pln"> value_of obj
obj</span><span class="pun">.</span><span class="pln">to_s
</span><span class="kwd">end</span>
<span class="kwd">end</span>
<span class="kwd">end</span>
<span class="typ">String</span><span class="pun">.</span><span class="pln">value_of </span><span class="lit">42</span> <span class="com"># => "42"</span></code>
This can also be written as a shorthand:
<code><span class="kwd">class</span> <span class="typ">String</span>
<span class="kwd">def</span> <span class="kwd">self</span><span class="pun">.</span><span class="pln">value_of obj
obj</span><span class="pun">.</span><span class="pln">to_s
</span><span class="kwd">end</span>
<span class="kwd">end</span></code>
Or even shorter:
<code><span class="kwd">def</span> <span class="typ">String</span><span class="pun">.</span><span class="pln">value_of obj
obj</span><span class="pun">.</span><span class="pln">to_s
</span><span class="kwd">end</span></code>
When inside a function definition,
self
refers to the object the function is being called with. In this case, class << self
opens the singleton class for that object; one use of that is to implement a poor man’s state machine:<code><span class="kwd">class</span> <span class="typ">StateMachineExample</span>
<span class="kwd">def</span><span class="pln"> process obj
process_hook obj
</span><span class="kwd">end</span><span class="pln">
private
</span><span class="kwd">def</span><span class="pln"> process_state_1 obj
</span><span class="com"># ...</span>
<span class="kwd">class</span> <span class="pun"><<</span> <span class="kwd">self</span>
<span class="kwd">alias</span><span class="pln"> process_hook process_state_2
</span><span class="kwd">end</span>
<span class="kwd">end</span>
<span class="kwd">def</span><span class="pln"> process_state_2 obj
</span><span class="com"># ...</span>
<span class="kwd">class</span> <span class="pun"><<</span> <span class="kwd">self</span>
<span class="kwd">alias</span><span class="pln"> process_hook process_state_1
</span><span class="kwd">end</span>
<span class="kwd">end</span>
<span class="com"># Set up initial state</span>
<span class="kwd">alias</span><span class="pln"> process_hook process_state_1
</span><span class="kwd">end</span></code>
So, in the example above, each instance of
StateMachineExample
has process_hook
aliased to process_state_1
, but note how in the latter, it can redefine process_hook
(for self
only, not affecting other StateMachineExample
instances) to process_state_2
. So, each time a caller calls the process
method (which calls the redefinable process_hook
), the behavior changes depending on what state it’s in.Alternative Answer:
In Ruby, there are three types of methods that can be applied to a class:
Instance methods and class methods are almost similar to their homonymous in other programming languages.
<code><span class="kwd">class</span> <span class="typ">Foo</span>
<span class="kwd">def</span><span class="pln"> an_instance_method
puts </span><span class="str">"I am an instance method"</span>
<span class="kwd">end</span>
<span class="kwd">def</span> <span class="kwd">self</span><span class="pun">.</span><span class="pln">a_class_method
puts </span><span class="str">"I am a class method"</span>
<span class="kwd">end</span>
<span class="kwd">end</span><span class="pln">
foo </span><span class="pun">=</span> <span class="typ">Foo</span><span class="pun">.</span><span class="pln">new
</span><span class="kwd">def</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">a_singleton_method
puts </span><span class="str">"I am a singletone method"</span>
<span class="kwd">end</span></code>
Another way of accessing an
Eigenclass
(which includes singleton methods) is with the following syntax (class <<
):<code><span class="pln">foo </span><span class="pun">=</span> <span class="typ">Foo</span><span class="pun">.</span><span class="pln">new
</span><span class="kwd">class</span> <span class="pun"><<</span><span class="pln"> foo
</span><span class="kwd">def</span><span class="pln"> a_singleton_method
puts </span><span class="str">"I am a singleton method"</span>
<span class="kwd">end</span>
<span class="kwd">end</span></code>
Now you can define a singleton method for
self
which is the class Foo
itself in this context:<code><span class="kwd">class</span> <span class="typ">Foo</span>
<span class="kwd">class</span> <span class="pun"><<</span> <span class="kwd">self</span>
<span class="kwd">def</span><span class="pln"> a_singleton_and_class_method
puts </span><span class="str">"I am a singleton method for self and a class method for Foo"</span>
<span class="kwd">end</span>
<span class="kwd">end</span>
<span class="kwd">end</span></code>
Answer:
%w(foo bar)
is a shortcut for ["foo", "bar"]
. Meaning it’s a notation to write an array of strings separated by spaces instead of commas and without quotes around them. You can find a list of ways of writing literals in zenspider’s quickref.Alternative Answer:
%w()
is a “word array” – the elements are delimited by spaces and it returns an array of strings.There are other % literals:
%r()
is another way to write a regular expression.%q()
is another way to write a single-quoted string (and can be multi-line, which is useful)%Q()
gives a double-quoted string%x()
is a shell command%i()
gives an array of symbols (Ruby >= 2.0.0)%s()
turns foo
into a symbol (:foo
)Answer:
<code><span class="pun">(</span><span class="lit">0.</span><span class="pun">..</span><span class="lit">8</span><span class="pun">).</span><span class="pln">map </span><span class="pun">{</span> <span class="pun">(</span><span class="lit">65</span> <span class="pun">+</span><span class="pln"> rand</span><span class="pun">(</span><span class="lit">26</span><span class="pun">)).</span><span class="pln">chr </span><span class="pun">}.</span><span class="pln">join</span></code>
<code><span class="pun">(</span><span class="lit">0.</span><span class="pun">..</span><span class="lit">50</span><span class="pun">).</span><span class="pln">map </span><span class="pun">{</span> <span class="pun">(</span><span class="str">'a'</span><span class="pun">..</span><span class="str">'z'</span><span class="pun">).</span><span class="pln">to_a</span><span class="pun">[</span><span class="pln">rand</span><span class="pun">(</span><span class="lit">26</span><span class="pun">)]</span> <span class="pun">}.</span><span class="pln">join</span></code>
And the last one that’s even more confusing, but more flexible and wastes fewer cycles:
<code><span class="pln">o </span><span class="pun">=</span> <span class="pun">[(</span><span class="str">'a'</span><span class="pun">..</span><span class="str">'z'</span><span class="pun">),</span> <span class="pun">(</span><span class="str">'A'</span><span class="pun">..</span><span class="str">'Z'</span><span class="pun">)].</span><span class="pln">map</span><span class="pun">(&:</span><span class="pln">to_a</span><span class="pun">).</span><span class="pln">flatten
string </span><span class="pun">=</span> <span class="pun">(</span><span class="lit">0.</span><span class="pun">..</span><span class="lit">50</span><span class="pun">).</span><span class="pln">map </span><span class="pun">{</span><span class="pln"> o</span><span class="pun">[</span><span class="pln">rand</span><span class="pun">(</span><span class="pln">o</span><span class="pun">.</span><span class="pln">length</span><span class="pun">)]</span> <span class="pun">}.</span><span class="pln">join</span></code>
Alternative Answer:
<code><span class="pln">require </span><span class="str">'securerandom'</span><span class="pln">
random_string </span><span class="pun">=</span> <span class="typ">SecureRandom</span><span class="pun">.</span><span class="pln">hex
</span><span class="com"># outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)</span></code>
SecureRandom also has methods for:
Answer:
You can use the
include?
method:<code><span class="pln">my_string </span><span class="pun">=</span> <span class="str">"abcdefg"</span>
<span class="kwd">if</span><span class="pln"> my_string</span><span class="pun">.</span><span class="pln">include</span><span class="pun">?</span> <span class="str">"cde"</span><span class="pln">
puts </span><span class="str">"String includes 'cde'"</span>
<span class="kwd">end</span></code>
Alternative Answer:
If the case is irrelevant, then a case-insensitive regular expression is a good solution:
<code><span class="str">'aBcDe'</span> <span class="pun">=~</span> <span class="pun">/</span><span class="pln">bcd</span><span class="pun">/</span><span class="pln">i </span><span class="com"># evaluates as true</span></code>
This will also work for multi-line strings.
Answer:
<code><span class="com">#!/usr/bin/env ruby</span>
<span class="pun">=</span><span class="kwd">begin</span>
<span class="typ">Every</span><span class="pln"> body mentioned this way
to have multiline comments</span><span class="pun">.</span>
<span class="typ">The</span> <span class="pun">=</span><span class="kwd">begin</span> <span class="kwd">and</span> <span class="pun">=</span><span class="kwd">end</span><span class="pln"> must be at the beginning of the line </span><span class="kwd">or</span><span class="pln">
it will be a syntax error</span><span class="pun">.</span>
<span class="pun">=</span><span class="kwd">end</span><span class="pln">
puts </span><span class="str">"Hello world!"</span>
<span class="pun"><<-</span><span class="pln">DOC
</span><span class="typ">Also</span><span class="pun">,</span><span class="pln"> you could create a docstring</span><span class="pun">.</span><span class="pln">
which</span><span class="pun">...</span><span class="pln">
DOC
puts </span><span class="str">"Hello world!"</span>
<span class="str">"..is kinda ugly and creates
a String instance, but I know one guy
with a Smalltalk background, who
does this."</span><span class="pln">
puts </span><span class="str">"Hello world!"</span>
<span class="com">##</span>
<span class="com"># most</span>
<span class="com"># people</span>
<span class="com"># do</span>
<span class="com"># this</span></code>
Alternative Answer:
<code><span class="pun">=</span><span class="kwd">begin</span>
<span class="typ">My</span><span class="pln">
multiline
comment
here
</span><span class="pun">=</span><span class="kwd">end</span></code>
In Conclusion
These are the most asked questions about the Ruby programming
language. If you have any suggestions or any confusion, please comment
below. We will be glad to help you.
Hope this article helped you.
This post was originally posted on DevPost.