Friday, May 2, 2008

Cheating is fun with the cheat gem!

errtheblog.com released a great gem called cheat.

Installation is a snap

$ sudo gem install cheat

Now you have access to a wide array of cheat sheets. Cheat sheets are basically like wiki pages that can be accessed from the command line, editable and all. Don't believe me? Give it a try

$ cheat rspec | less

rspec:
INSTALL
=======
INSTALL rspec
=============
$ sudo gem install rspec
OR
$ ./script/plugin install git://github.com/dchelimsky/rspec.git

INSTALL rspec_on_rails plugin
=============================
$ ./script/plugin install git://github.com/dchelimsky/rspec-rails.git


BOOTSTRAP THE APP
=================
$ ./script/generate rspec
create spec
create spec/spec_helper.rb
create spec/spec.opts
create previous_failures.txt
create script/spec_server
create script/spec

....

Cheat is not even rails specific. There are a whole slue of helpful commands that you can refer to as you go about your everyday programming. Just use the cheat sheets command to list them all.

$ cheat sheets
All Cheat Sheets:
acts_as_authenticated
acts_as_state_machine
acts_as_taggable_on
address
administrateme
agile
alias
ambition
ansi
arts
as3_formulas
ascii
assert
assertions
assert_block

....and it keeps going and going

Include vs Extend

A common cause of confusion in Ruby is discerning the difference between Module#include and Object#extend and when to use one over the other.

A few examples will help us understand. Lets create a file example.rb

cd module Coolness
def cool_method
puts "This is one cool method!"
end
end

class A
include Coolness
end

a = A.new
a.cool_method


Then we run it

$ ruby example.rb
This is one cool method!


When you include a module from another module (remember all classes are modules) you are in essence adding in all of the included module's constants, methods, and module variables to the module that is including it. It's a mouthful, I know. So all of the methods of the module are available as instance methods. Now lets see what happens when we modify our file and use extend instead.

class A
extend Coolness
end

a = A.new
a.cool_method


$ ruby example.rb
example.rb:14: undefined method `cool_method' for # (NoMethodError)


When you use extend you are adding the modules methods to the instance from which it is called on. In our case we are extending the module from the singelton class A so all the modules methods are available on the singelton class A, not on the instances of class A. I know, its another mouthful. So when you use extend in this way you are in essence adding the modules methods as class methods, not instance methods. So to execute cool_method we must call it as a method the class A itself.

class A
extend Coolness
end

A.cool_method


$ ruby example.rb
This is one cool method!


If we wanted cool_method to be available to an instance of class A we need to explicitly extend the instance.

class A
extend Coolness
end

a = A.new
a.extend(Coolness)
a.cool_method


$ ruby example.rb
This is one cool method!


So to summarize if you wanted to add instance methods to a class you should use include. If you want to add class methods to a class you should use extend. And finally, if you want to add instance methods to one particular instance of a class you should use extend on the instance itself.

Let me know if you have any questions.