Rubyisms That Ruby Programmers Should Know 3

Posted by Carsten Nielsen
on Monday, September 29

There are a few things that I know now and take for granted which used to blow my mind. If only someone took the 10 minutes to explain these concepts to me back when I started programming I would have been in the know so much sooner. Hopefully I can be that someone for you if you are stuck on any of these yourself.

The Splat


def stuff(*args)
  args.inspect
end

stuff 1, 'neck', :blog # => [1, 'neck', :block]

Splats are basically like telling your method to take as many arguments as it wants and put them in an array called, in this case, args. You can name your splat anything you’d like. Splats can also appear along with other arguments in a method definition like this:


def say_jobs(person, *tasks)
  puts "#{person} will: #{tasks.join(', ')}."
end

say_jobs 'Carsten', 'clean floor', 'make dinner', 'bake a pie'
# => 'Carsten will clean floor, make dinner, bake a pie.'

You might also see a splat appear backwards in the form of a list assignment like this:


malted_battery_acids = ['Coke', 'Pepsi', 'RC Cola']
coke, pepsi, rc_cola = *malted_battery_acids

Array of Words


%w[cat dog bat hat]      # => ['cat', 'dog', 'bat', 'hat']
%w[carsten\ nielsen hat] # => ['carsten nielsen', 'hat']

This is a simple macro which creates an array of strings. It is whitespace sensitive, so it treats everything between spaces as a separate word. You can escape spaces to create words with spaces in them but just keep in mind that it can get confusing for others to read when you start doing stuff like that.

It should also be noted that I chose to use square brackets as start and end delimiters, but you can use curly braces, quotes, bars, most anything you’d like for all the percent-style literals.

Alternative String Literals


%{greetings good sir}  # <- Allows interpolation.
%q{greetings good sir} # <- No interpolation.
%Q{greetings good sir} # <- Allows interpolation.

You can think of these as the heredoc for minimalists. If you use a lowercase q it behaves like a single quoted string, otherwise you have full interpolation like a double quoted string.

Shelling Out


`which ruby`   # => '/opt/local/bin/ruby'
%x{which ruby} # => '/opt/local/bin/ruby'

Whatever you place between the back-ticks is sent to the shell, the results are returned as a string. There is an alternate style too that behaves the same.

The Blarg (Block Argument)


def quote(&block)
  "&ldquo;#{block.call}&rdquo;"
end

quote { 'Johnny Walker Black' }
# => '&ldquo;Johnny Walker Black&rdquo;'

Blargs are great when you have a method that requires a block. If you call the method without a block it will raise an error at runtime. In my example I reference the block by it’s blarg’s name but you can use yield too.

Informative & Painless URIs

Posted by Carsten Nielsen
on Saturday, June 21

There is just something nice about those cute URIs that we have all grown to love, I’m sure you’ve seen them around: http://pork.ham/lists/32-grocery-list. Guess what, these are fun and easy to implement, here’s how!

First we need a method that can convert a normal title or name into something safe for use in a URI, here’s my answer:


class ::String

  # Returns a version of self that is safe for inclusion in a URI.
  def urilize
    strip.
    gsub(' ', '-').
    gsub(/[-]+/, '-').
    gsub('&', 'and').
    downcase.
    scan(/[a-z0-9\-]*/).to_s
  end

end

Users enter the darnedest data, so your urilize implementation will probably be tweaked over time. Anyways, the above String extension let’s us do stuff like:


'My Name Is Mud!'.urilize # => "my-name-is-mud"
'Awesome  &  Cool Stuff!!!'.urilize # => "awesome-and-cool-stuff"

Now we need a seamless way to get this functionality into our models so that they start throwing around all of these cool URIs for free. My answer to this is a sweet and simple mixin:


module Findable

  def to_param
    to_s.blank? ? id.to_s : "#{id}-#{to_s.urilize}"
  end

end

In order for our mixin to work we need our ActiveRecord models to have an overloaded to_s method that returns the title or name of the object. This is good practice and you should be doing it in any model where it makes sense to do so.

Anyways we can use our mixin as follows:


class Ticket < ActiveRecord::Base

  include Findable

  ...

  def to_s
    title
  end

  ...

end

Now imagine we have the following ticket in our database:


id: 6
created_by: Captain Obvious
assigned_to: Developer Dude
title: Feature Improvements
body: This massive feature that you implemented in far too little time is imperfect!

Assuming resourceful routes for Tickets we can do something like:


ticket = Ticket.find(6)
ticket_path(ticket) # => "/tickets/6-feature-improvements"

Neat.

Method Name Hack

Posted by Carsten Nielsen
on Friday, June 13

Ruby lets you do some pretty fun stuff, from highly elegant and useful to interesting and hacky. This is more of a hack than anything but it demonstrates some cool concepts.


module ::Kernel

  private
  # Allows you to get the name of the current method inside that method.
  # Example:
  #
  #   def hello
  #     __method_name__
  #   end
  #
  #   hello # => "hello"
  def __method_name__
    caller[0].scan(/`(.*)'/).to_s
  end

end

Ruby let’s you extend anything and everything, which is pretty powerful. The two preceding colons in ::Kernel tell Ruby to access the Kernel module in the global object space, if we were already there they would not be necessary but to be safe it’s best to add them.

Ruby maintains a call stack which is basically an array of strings that look like:


/Users/carsten/Projects/coolness/cool.rb:12:in `awesome_method'

This lets us know the path and file name as well as the line number and method name; neat. Then we just do a cute little regular expression scan and we can see the name of the method we are inside of.