Helpful Command-Line Flags

The -c and -w command-line flags for ruby mean check for syntax errors and check for questionable Ruby, respectively.

ruby -cw program.rb

The difference between “load” and “require”

Semantically speaking, you load a file, but you require a feature. Also, require doesn’t reload files, but load does, if it’s called again.

Double exclamation

Use double exclamation points to check if an object is not nil.

obj = Object.new
!obj == false
!(!obj) == !(false) == true
!!obj == !obj.nil?

Understanding Ruby object message

In Ruby, all values and data structures are objects. 1, @dog, and ["blog"] are objects even though they are instances of different classes. Every object also understands a set of messages. To send an object a message, use the dot operator to the right of the object and type the message. For example

> dog = Dog.new
> dog.bark # Send the bark message to the dog object.

After the message is sent to the dog object, the corresponding method is called. So far, this seems like really complicated talk for the simple concept of calling a method, but it is necessary.

For example, you might send an object a message that doesn’t correspond to a method. But due to Ruby’s introspective powers, you can intercept that message and call some other methods. That’s what libraries in Ruby on Rails do. ActiveRecord uses message interception to determine the corresponding database columns it should look at.

> Workout
=> Workout(id: integer, workout_date: datetime, created_at: datetime, updated_at: datetime, user_id: integer)
> Workout.find_by_user_id(1)
Workout Load (0.9ms)  SELECT "workouts".* FROM "workouts" WHERE "workouts"."user_id" = 1 LIMIT 1
=> #<Workout id: 1, workout_date: "2013-04-02 13:00:00", created_at: "2013-04-14 19:22:31", updated_at: "2013-04-14 19:22:31", user_id: 1>

Did I have to define a method find_by_user_id? Nope, ActiveRecord intercepts the message find_by_user_id. It then parses it and sees that I’m trying to find by the user_id table column, and it fetches the records with the matching columns. See how such the simple concept of message interception can lead to powerful results?

The difference between instance method and method

String.instance_methods == "abc".methods    # => true
String.methods == "abc".methods             # => false

Search for a method

I sometimes switch from programming in C# to Python to Java to Ruby (not all in one day!). Just like learning Spanish and Italian, it’s easy to mix up which word belongs to which language. In the case of programming languages, it’s easy to forget, does a String class in Ruby use the length or size method? Use the following snippet to search for methods within a class.

String.instance_methods(false).grep(/size|length/)

The code above says for the String class, return to me all instance methods and don’t give me the ones that it’s inherited from ancestor classes. Within that array of instance methods, find a symbol that contains the word size or the word length.

Fortunately, since one of the core principle’s of Ruby’s philosophy is to make programmers happy, Ruby contains both String#size and String#length.

Ruby’s private keyword

Ruby’s private keyword is different from C++ and Java’s private keyword. The “private rule”, from Paolo Perrotta’s excellent Metaprogramming Ruby: Program Like the Ruby Pros, states that a private method comes about from two rules acting together

  1. in order to call a method on an object that is NOT yourself, you need to specify explicitly the receiver

  2. private methods can only be called with an implicit receiver

As a corollary, you can’t call a private method on an object even with self as the explicit receiver.

Let’s see this rule in action:

class Dog
  def bark
    puts "bark"
  end

  private
  def disassociate_from_other_dogs
    puts "disassociate from other dogs"
  end
end

# in console
> self
=> main
> dog = Dog.new
=> #<Dog:0x007fd5010e4628>
> dog.disassociate_from_other_dogs
NoMethodError: private method `disassociate_from_other_dogs' called for #<Dog:0x007fd5010e4628>
> 

Why couldn’t we call disassociate_from_other_dogs on dog? Let’s apply the rule! self, refers to main, so the object dog is not yourself. Thus, in order to call a method on dog, we need to specify the receiver explicitly. Okay, we’ve specified we’re calling the method on dog. However, disassociate_from_other_dogs is a private method. According to the second rule, private methods can only be called with an implicit receiver. But we’re explicitly specifying the object. So why don’t we implicitly specify the object is dog? We can’t because self refers to main. Thus, we can’t call the private method on dog.

There is a way to call an object’s private method: simply use the Object#send method that all objects inherit.

> dog.send(:disassociate_from_other_dogs)

But this violates the rule! Honestly, I don’t know what to make of this, but it seems the Ruby core contributors don’t either.