Ruby Quicktips Logo

Ruby Quicktips

Random Ruby and Rails tips.
This blog is dedicated to deliver short, interesting and practical tidbits of the Ruby language and Ruby on Rails framework. Read more...

Your submissions are more than welcome!
Aug 22 ’11

Directly access an object if it’s present

If you want to access an object only if it’s present, you can use Rails’ Object#presence.
The API docs on presence have a good explanation:

This is handy for any representation of objects where blank is the same as not present at all. For example, this simplifies a common check for HTTP POST/query parameters:

state = params[:state] if params[:state].present?
country = params[:country] if params[:country].present?
region = state || country || 'US'

…becomes:

region = params[:state].presence || params[:country].presence || 'US'

12 notes 0 comments

Jun 15 ’11

It’s now rubyquicktips.com

This blog now has its own domain.
http://rubyquicktips.tumblr.com is now http://rubyquicktips.com.

3 notes 0 comments

Jun 13 ’11

Check if your associations have been eager loaded

If you want to check if associations of an object have been eager loaded, use the loaded? method:

@blogpost = Post.includes(:comments).find(1)
@blogpost.comments.loaded?
=> true
@blogpost = Post.find(1)
@blogpost.comments.loaded?
=> false

This might for example be useful to test eager loading in your tests.

4 notes 0 comments

Jun 11 ’11

Eager loading

When you load records from the database and also want to access the associated objects for each of these records, it’s a good idea to make use of eager loading. Eager loading reduces the amount of queries made to the database and therefor increases performance.
A good example is an index view where you want to display an overview of information on a particular group of objects, including their associations (for example, if you want to display a list of blogposts and for each of these posts the last - say - three comments).

To make use of eager loading, you can use the :include parameter (Rails 2) or the includes method (Rails 3) respectively when doing your ActiveRecord finds.

# Rails 2
Blogpost.all(:include => :comments)
# Rails 3
Blogpost.includes(:comments).all

You can also load more than one association and nest the include statements using Arrays and Hashes:

# Rails 2
Blogpost.all(:include => [:tags, { :comments => :commenter }])
# Rails 3
Blogpost.includes(:tags, { :comments => :commenter }).all

Exactly one database query is performed for each model you want to load.
If you want to know more about eager loading, including why and when to use it, check out the Rails Guide on eager loading.

22 notes 0 comments

Jun 2 ’11

Spread command chains across multiple lines

Ruby’s syntax allows you to spread command chains across multiple lines:

puts "You can do a lot with this in one line".reverse.sub('eno', 'elpitlum').sub(' htiw tol a', '').reverse.<< 's, too!'

…can also be written like this:

puts "You can do a lot with this in one line".
reverse.
sub('eno', 'elpitlum').
sub(' htiw tol a', '').
reverse.
<< 's, too!'

In Ruby < 1.9 you have to place the dot at the end of the line, like shown in the example above. From Ruby 1.9 on, you can also place the dot at the beginning of the next line, right before the next command call.

1 note 0 comments

May 26 ’11

Execute shell commands

There are a number of different ways to run shell commands from Ruby.

The exec command

Kernel#exec replaces the current process and runs the command:

exec('ls ~')
# Nothing after this command is executed

This might be a bit impractical, so have a look at the other options.

Backticks or %x shortcut

Place your command inside backticks (`) or execute it within %x() and it will return the output of this command:

`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"

The system command

Use Kernel#system and it will return true (command run successfully), false (unsuccessful) or nil (command execution failed):

system('ls ~')
=> true

For all of these methods, you can access the PID and exit status of the unix process via the $? variable:

$?.pid
=> 11988
$?.exitstatus
=> 0

There are more options and I recommend these resources for more details:

31 notes 0 comments

May 9 ’11

Hash: new create syntax

Additional to the syntax for creating hashes we all know:

hash = { :first => "ruby", :second => "rails" }
# => {:first=>"ruby", :second=>"rails"}
hash[:first] # => "ruby"

…Ruby > 1.9.1 adds support for another syntax:

hash = { first: "ruby", second: "rails" }
# => {:first=>"ruby", :second=>"rails"}
# you still have to access a value via a symbol
hash[:second] # => "rails"
hash[second] # NameError

7 notes 0 comments

May 4 ’11

Merge or reverse_merge a Hash

Ruby’s Hash#merge lets you merge two Hashes. Duplicate entries in the merged Hash taking precedence over then ones in the calling Hash:

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1 #=> {"a"=>100, "b"=>200}

Rails’ Hash#reverse_merge takes the opposite approach when it comes to handle duplicate entries. The API docs perfectly describe what it’s good for, giving an example of a very common practise regarding a method’s options:

Allows for reverse merging two hashes where the keys in the calling hash take precedence over those in the other_hash. This is particularly useful for initializing an option hash with default values:

def setup(options = {})
 options.reverse_merge! :size => 25, :velocity => 10
end

Using merge, the above example would look as follows:

def setup(options = {})
 { :size => 25, :velocity => 10 }.merge(options)
end

The default :size and :velocity are only set if the options hash passed in doesn’t already have the respective key.

Both methods are also available in their Bang versions merge! and reverse_merge!.

Here are the docs: Hash#merge (Ruby) and Hash#reverse_merge (Rails).

All code examples taken from the respective API docs.

22 notes 0 comments

May 2 ’11

Parse a string into a DateTime object. Controlled.

Just as you can format a string from a Time object with Time#strftime, you can also parse a string in a defined format into a DateTime or Date object, using DateTime#strptime or Date#strptime respectively (Date#strptime only creates a date without the time, though).

require 'date'
parsed_time = DateTime.strptime('03/05/2010 14:25:00', '%d/%m/%Y %H:%M:%S')
parsed_time.to_s
=> "2010年05月03日T14:25:00+00:00"

See the docs for more info: DateTime#strptime and Date#strptime.

3 notes 0 comments

Apr 14 ’11

Using “try” with a hash to check existence of a key

The try method is awesome. Check the documentation.
It is usually used to call a method on an object if it exists, or return nil if it doesn’t.

But sometimes, it is not used with hashes, but this also works perfectly:

params[:search] ? params[:search][:name] : nil
# Can also be written as...
params[:search].try(:[],:name)

Clean!

This tip was submitted by Miguel Camba.

31 notes 0 comments

Apr 11 ’11

Format a string from a Time object

If you only want to print the first day of the current month you can use the string formating method on a Time object:

> Time.now.strftime("%Y-%m-1")
"2011年04月1日"

The method can be used to print date in almost any format:

> Time.now.strftime("%A %B %d or %a %e/%m")
=> "Monday April 11 or Mon 11/04"

Check out Time#strftime for a list of directives. Time is part of the core, so there is no need to require anything.

This tip was submitted by Aqab Bin Talal.

1 note 0 comments

Apr 8 ’11

Heredoc and Indent

Heredocs come in handy when you have to deal with larger multi-line strings in the source code itself. However, it usually breaks the indents:

class Poem
 def initialize
 @text = <<END
"Faith" is a fine invention
When Gentlemen can see
But Microscopes are prudent
 In an Emergency.
(Emily Dickinson 1830-1886)
END
 end
 def recite
 puts @text
 end
end

But it wouldn’t be Ruby if there were no way to make this pretty. The minus in -END makes sure any whitespace before the end marker is ignored and the first six spaces of every line are cut when the string collected by heredoc is post processed with gsub:

class Poem
 def initialize
 @text = <<-END.gsub(/^ {6}/, '')
 "Faith" is a fine invention
 When Gentlemen can see
 But Microscopes are prudent
 In an Emergency.
 (Emily Dickinson 1830-1886)
 END
 end
 def recite
 puts @text
 end
end

The result for both snippets is exactly the same – provided you stick to the recommended 2 spaces indent for Ruby source code:

>> Poem.new.recite
"Faith" is a fine invention
When Gentlemen can see
But Microscopes are prudent
 In an Emergency.
(Emily Dickinson 1830-1886)

This tip was submitted by Sven Schwyn and originally posted on his blog.

26 notes 0 comments

Feb 24 ’11

Rails 3 Validation Shortcut

In Rails 2 the only way to add multiple validations to a field is through separate validate statements:

validates_presence_of :title
validates_length_of :title, :maximum => 30

Rails 3 simplifies this process by adding a method called validates which is a “shortcut to all default validators”. Using the validates method your code will look like this:

validates(:title, :presence => true, :length => {:maximum => 30})

You can find more information about this method in the API documentation here.

13 notes 0 comments

Feb 21 ’11

How to define infinite numbers

You can define the “number” ‘infinity’ (or ’-infinity’) in Ruby like this:

1.0/0
=> Infinity
-1.0/0
=> -Infinity

Infinity and -Infinity behave just like you expect them to: they are always bigger - or always smaller, respectively - than any number you compare it to.
The Xing Devblog had a great post recently about using Ruby’s infinity in Rails, with some thoughts on when you might want to use it (or not).

P.S.: the Float class in Ruby 1.9.2 provides an Infinity constant you can use:

Float::INFINITY
=> Infinity

This tip was submitted by makoto.

12 notes 0 comments

Feb 18 ’11

Grep an object’s available methods

Because Object.methods returns an array, you can grep that just like in this tip about grepping anything from your enumerables.
For example, if you are looking for a particular method of an object, you can easily narrow down the results like this:

Object.methods.grep /inspect/
=> ["inspect", "pretty_inspect", "pretty_print_inspect"]

This tip was submitted Adam Rogers.

7 notes 0 comments

[フレーム]

AltStyle によって変換されたページ (->オリジナル) /