Thursday, March 27, 2014

Ruby Gotchas


Most Ruby on Rails beginners get excited by the framework and start crafting applications without any knowledge of the language. And there’s nothing wrong about it. At least, unless those beginners persist in such approach and become senior developers without any knowledge of the language.

Anyway, sooner or later, beginners or experienced programmers, we all run into so-called Ruby Gotchas – those small subtleties that hide from our sight for hours of hardcore debugging (logger.debug "*** #{object} ****") and then we go Ohh..That was that??! Really, this time I WILL read that book with a hammer on the cover! Or, rather, we go shit! and fall asleep.

Here is a list of popular Ruby gotchas and curiosities that developers should be aware of. For each case, there’s an example of confusing and/or error-prone code.




and / or is NOT the same as && / ||

 surprise = true and false # => surprise is true
 surprise = true && false  # => surprise is false

Good practice
 Use only && / || operators.

In detail
  • and / or operators have lower precedence than && / ||
  • and / or have lower precedence than = assignment operator, while && / || are of higher precedence
  • and and or have the same precedence, while && has higher precedence than ||
The first example becomes clearer when we add parentheses that illustrate how using `and` differs from `&&`:

(surprise = true) and false # => surprise is true
surprise = (true && false)  # => surprise is false

Some say: use and / or for flow control and && / || for boolean operations. I will say: don’t use keyword versions (and / or / not) at all (and go with more verbose ifs and unlesses). Less ambiguity, less confusion, less bugs.
More: Difference between “or” and || in Ruby?


eql? is NOT the same as == (and NOT the same as equal? or ===)

1 == 1.0   # => true
1.eql? 1.0 # => false

Good practice
 Use only == operator.

In detail

 ==, ===, eql? and equal? are all different operators, meant for different usage in different situations.  You should always use == operator for comparing things, unless you have some specific needs (like  you really need to differ 1.0 from 1) or manually override one of the equality operators for whatever  reason.

 Yes, the eql? version may look smarter than plain old == comparison, but does it really do what you meant it to do, like, just compare some things?
More: What’s the difference between equal?, eql?, ===, and ==?



a ||= b is not a = a || b


A common misconception is that a ||= b is equivalent to a = a || b, but it behaves like a || a = b

In a = a || b, `a` is set to something by the statement on every run, whereas with a = || a = b, `a` is only set if `a` is logically false (i.e. if it's nil or false) because || is 'short circuiting'. That is, if the left hand side of the || comparison is true, there's no need to check the right hand side.

An example goes here: 

h = {}

def h.[]=(k, v)
  puts "Setting hash key #{k} with #{v.inspect}"
  super
end

# 1. The standard ||= approach
h[:x] ||= 10
h[:x] ||= 20

# 2. The a = a || b approach
h[:y] = h[:y] || 10
h[:y] = h[:y] || 20

# 3. The a || a = b approach
h[:z] || h[:z] = 10
h[:z] || h[:z] = 20


Output:

Setting hash key x with 10
Setting hash key y with 10
Setting hash key y with 10
Setting hash key z with 10
 
here y is unnecessarily set twice because of the general approach we consider.


Note : Do not confuse [op]= with anything related to ||= or &&=. They're entirely different ideas and are implemented entirely different[ly].


super is NOT the same as super()

class Foo
  def show
    puts 'Foo#show'
  end
end

class Bar < Foo
  def show(text)
    super

    puts text
  end
end

Bar.new.show('test') # ArgumentError: wrong number of arguments (1 for 0)

Good practice
 This is one of the places where omitting the parentheses is not only a matter of taste (or conventions),  but actually changes the program logic.

In detail
  • super (without parentheses) will call parent method with exactly the same arguments that were passed to the original method (so super inside Bar#show becomes super('test') here, causing an error, because parent method does not take any arguments).
  • super() (with parentheses) will call parent method without any arguments, just as expected.
More: Super keyword in Ruby


Your exception must not be an Exception

class MyException < Exception
end

begin
  raise MyException
rescue
  puts 'Caught it!'
end

# MyException: MyException
#       from (irb):17
#       from /Users/amit/.rbenv/versions/2.1.0/bin/irb:11:in `<main>'
(This code will not catch MyException and the message 'Caught it!' will not be displayed.)

Good practice
  • When defining your own exception class, inherit from StandardError or any of its descendants (the more specific, the better). Never use Exception for the parent.
  • Never rescue Exception. If you want to do some general rescue, leave rescue statement empty (or use rescue => e to access the error).
In detail
  • When you leave rescue statement empty, it means it will catch exceptions that inherit from StandardError, not Exception.
  • When you rescue Exception (which you should not), you’ll catch errors you won’t be able to recover from (like out of memory error). Also, you’ll catch system signals like SIGTERM, and in effect you won’t be able to terminate your script using CTRL-C.
More: Why is it bad style to `rescue Exception => e` in Ruby?


class Foo::Bar is NOT the same as module Foo; class Bar

MY_SCOPE = 'Global'

module Foo
  MY_SCOPE = 'Foo Module'

  class Bar
    def scope1
      puts MY_SCOPE
    end
  end
end

class Foo::Bar
  def scope2
    puts MY_SCOPE
  end
end

Foo::Bar.new.scope1 # => "Foo Module"
Foo::Bar.new.scope2 # => "Global"

Good practice
 Always use longer, more verbose version with classes wrapped by modules:
 module Foo
   class Bar
   end
 end

In detail
  • module keyword (as well as class and def) will create new lexical scope for all the things you put inside. So, our module Foo creates the scope 'Foo' in which our MY_SCOPE constant with 'Foo Module' value resides.
  • Inside this module, we declare class Bar, which creates new lexical scope (named 'Foo::Bar'), which has access to its parent scope ('Foo') and all constants declared in it.
  • However, when you declare Foo::Bar with this :: “shortcut”: class Foo::Bar, it creates another lexical scope, which is also named 'Foo::Bar', but here, it has no parent, and thus, no access to things from 'Foo' scope.
  • Therefore, inside class Foo::Bar, we have only access to MY_SCOPE constant declared at the beginning of the script (without any module) with value 'Global'.
More: Ruby – Lexical scope vs Inheritance


Most bang! methods return nil when they do nothing

'foo'.upcase! # => "FOO"
'FOO'.upcase! # => nil

Good practice
 Never depend on built-in bang! methods return value, e.g. in conditional statements or in control flow:
 @name.upcase! and render :show
 Above code can cause some unpredictable behaviour (or, to be more specific, very predictable failure  when @name is already in uppercase). Also, it is another example why you should not use and / or  for control-flow shortcuts. No trees will be cut if you add those two enters there:
 @name.upcase!

 render :show


attribute=(value) method always returns passed value, regardless of method return value

class Foo
  def self.bar=(value)
    @foo = value

    return 'OK'
  end
end

Foo.bar = 3 # => 3
(Note that the assignment method bar= returns 3 even though we explicitly return 'OK' at the end of its body.)

Good practice
 Never rely on anything that happens inside assignment method, eg. in conditional statements like this:
 puts 'Assigned' if (Foo.bar = 3) == 'OK' # => nil
 This will obviously not work.
 More: ruby, define []= operator, why can’t control return value?


private will NOT make your self.method private

class Foo

  private
  def self.bar
    puts 'Not-so-private class method called'
  end

end

Foo.bar # => "Not-so-private class method called"
(Note that if the method were private, Foo.bar would raise NoMethodError.)

Good practice
 In order to make your class method private, you have to use private_class_method :method_name  or put your private class method inside class << self block:

 class Foo

  class << self
    private    
    def bar
      puts 'Class method called'
    end    
  end

  def self.baz
    puts 'Another class method called'
  end
  private_class_method :baz

 end

Foo.bar # => NoMethodError: private method `bar' called for Foo:Class
Foo.baz # => NoMethodError: private method `baz' called for Foo:Class
More: creating private class method


I ain’t afraid of no Ruby Gotchas

Ruby gotchas listed above may not look like a big deal, and at first sight they may seem they are simple matter of aesthetics or conventions.

Trust me – if you don’t deal with them, eventually they will lead to some nasty headaches during Ruby on Rails development. And will cause heartbreak. Because you’ll fall out of love with Ruby. And then you’ll stay alone. Forever... ;)

Monday, January 20, 2014

Executing Commands in Ruby


Ruby allows many different ways to execute commands or sub-processes. Here I will list few of them
1) Backtick
2) system
3) exec
4) sh
5) popen3

Backtick ( `cmd` ) :

backtick returns the output of the cmd  in a subshell.

output = `ls` puts "output is #{output}"

Result of the above code is 

$ ruby test.rb output is amit.txt test.rb

Here the backtick operation forks the master process and the operation is executed in a new process. However this is a blocking operation. The main application waits until the result of backtick operation completes.
If there is an exception in the sub-process then that exception is given to the main process and the main process might terminate if exception is not handled.
In the following case I am executing xxxxx which is not a valid executable name.
outut = `xxxxxxx` puts "output is #{output}"
Result of above code is : 
$ ruby test.rb test.rb:1:in ``': No such file or directory - xxxxxxx (Errno::ENOENT) from test.rb:1:in `<main>'
Notice that puts was never executed because the backtick operation raised exception. To check the status of the backtick operation you can execute $?.success?
output = `ls` puts "output is #{output}" puts $?.success?

Notice that the last line of the result contains true because the backtick operation was a success.

$ ruby main.rb output is lab.rb main.rb true


system : 


system behaves a bit like backtick operation. However there are some differences.
First let’s look at similarities.
Just like backticksystem is a blocking operation. You can get the result of the operation using $?.success? . systemoperations are also executed in a subshell.
Now the differneces between backtick and system .

system eats up all the exceptions. So the main operation never needs to worry about capturing an exception raised from the child process.
output = system('xxxxxxx') puts "output is #{output}"
Result of the above operation is given below. Notice that even when exception is raised the main program completes and the output is printed. The value of output is nil because the child process raised an exception.
$ ruby test.rb output is
Another difference is that system returns true if the command was successfully performed ( exit status zero ) . It returns false for non zero exit status. Returns nil if command execution fails.
exec : 
exec replaces the current process by running the external command. Let’s see an example.
Here I am in irb and I am going to execute exec('ls').
$ irb e1.9.3-p194 :001 > exec('ls') amit.rb test.rb amitk ~/dev/lab 1.9.3 $
I see the result but since the irb process was replaced by the exec process I am no longer in irb .
Behind the scene both system and backtick operations use fork to fork the current process and then they execute the given operation using exec .
Since exec replaces the current process it does not return anything if the operation is a success. If the operation fails then `SystemCallError is raised.
sh : 
sh actually calls system under the hood. However it is worth a mention here. This method is added by FileUtils in rake. It allows an easy way to check the exit status of the command.
require 'rake' sh %w(xxxxx) do |ok, res| if !ok abort 'the operation failed' end end
popen3 : 
If you are going to capture stdout and stderr then you should use popen3 since this method allows you to interact with stdinstdout and stderr .
I want to execute git push heroku master programmatically and I want to capture the output. Here is my code.
require 'open3' cmd = 'git push heroku master' Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr| puts "stdout is:" + stdout.read puts "stderr is:" + stderr.read end
And here is the output. It has been truncated since rest of output is not relevant to this discussion.
stdout is: stderr is: Heroku receiving push Ruby/Rails app detected Installing dependencies using Bundler version 1.2.1
Lets see an example of capturing streaming output.
require 'open3' cmd = 'ping www.google.com' Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr| while line = stdout.gets puts line end end
In the above case you will get the output of ping on your terminal as if you had typed ping www.google.com on your terminal .
Now let’s see how to check if command succeeded or not.
require 'open3' cmd = 'ping www.google.com' Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr| exit_status = wait_thr.value unless exit_status.success? abort "FAILED !!! #{cmd}" end end

Hope this post helps in understanding the basics of executing commands from our program.
Happy Coding... :)