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 18 ’12

Quick Hash to a URL Query trick

Got a hash of values you want to convert into a url query string? Use the to_query method:

"http://www.example.com?" + { language: "ruby", status: "awesome" }.to_query
# => "http://www.example.com?language=ruby&status=awesome" 

Want to do it in reverse? Use CGI.parse:

require 'cgi' # Only needed for IRB, Rails already has this loaded
CGI::parse "language=ruby&status=awesome"
# => {"language"=>["ruby"], "status"=>["awesome"]} 

Both methods support nested values.

This tip was submitted by Victor Solis.

9 notes 0 comments

Apr 17 ’12

Create a hash from an array with Hash[*arr]

The Hash::[] class method can be used in addition to the splat operator to create a hash from an array.

arr = [:a, 1, :b, 2]
Hash[*arr]
# => {:a => 1, :b => 2}

6 notes 0 comments

Mar 27 ’12

Mark Deprecated Code in Ruby

To mark deprecated code in Ruby simply add a comment to the rdoc and call the Kernel#warn method. For example:

class Foo
  # DEPRECATED: Please use useful instead.
  def useless
    warn "[DEPRECATION] `useless` is deprecated.  Please use `useful` instead."
    useful
  end

  def useful
    # ...
  end
end

If you’re using Yard instead of rdoc, your doc comment should look like this:

# @deprecated Please use {#useful} instead

Also, don’t forget to remove the deprecated method in some future release.

Source: Ryan McGeary’s answer on stackoverflow.

9 notes 0 comments

Mar 22 ’12

Using Hash as Recursive Function with Memoization

We can define a new Hash in a smart way by using Hash#new and passing it a block:

h    = Hash.new {|hash,key| hash[key] = hash[key-1] + hash[key-2]}
h[1] = 0
h[2] = 1

puts h[3] #=> 1
puts h[100] #=> 218922995834555169026

Here an example of famous Collatz Conjecture:

h    = Hash.new {|hash,n| hash[n] = 1 + (n.odd? ? hash[3*n+1] : hash[n/2])}
h[1] = 1

puts h[100] #=> 26
puts h[1000] #=> 112

via: thoughbot’s blog

3 notes 0 comments

Mar 20 ’12

Block style comments

Wrap a block of code within =begin and =end to comment it out.

# the comment format you're used to
puts "I am evaluated"

=begin
puts "I"
puts "am"
puts "commented"
puts "out"
=end

This tip was submitted by Tim Linquist.

6 notes 0 comments

Mar 15 ’12

Method chaining with inject

Aim: perform a method chaining based on hash

Required operation:

ErrorLog.event_eq([3, 7]).subdomain_like("default").user_id_eq(100)

Given:

search_opts = { :event_eq => [3, 7], :subdomain_like => "default", :user_id_eq => 100 }

Solution:

search_opts.inject(ErrorLog) { |memo, (k, v)| memo.send(k, v) }

This tip was submitted by sumskyi.

2 notes 0 comments

Mar 8 ’12

Convert between number bases easily

It’s often a requirement in various projects to convert numbers from decimal to text representations of several other bases, such as hexadecimal or binary.
Did you know you can convert to any base from 2 to 36 in one line in Ruby?

Using the Fixnum#to_s method, you can quickly convert any Fixnum object to the textual format of another base:

255.to_s(36) #=> "73"
255.to_s(16) #=> "ff"
255.to_s(2)  #=> "11111111"

This tip was submitted by Nathan Kleyn.

6 notes 0 comments

Mar 6 ’12

Some Array magic using transpose, map and reduce

To add on corresponding elements of several arrays:

a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]

[a, b, c].transpose.map { |x| x.reduce :+ }
# => [12, 15, 18]

Given a number of arrays, each contains same number of arrays with the same length. To merge corresponding arrays:

a = [ [1, 2], [3, 4] ]
b = [ [5, 6], [7, 8] ]
c = [ [9, 10], [11, 12] ]

(a.transpose + b.transpose + c.transpose).transpose
# => [[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]]

To do the same job, but with arrays that are not necessarily equal in length:

a = [ [1], [2, 3] ]
b = [ [4, 5], [] ]
c = [ [6,7,8], [9, 10, 11, 12] ]

[a, b, c].transpose.map { |x| x.reduce :+ }
# => [[1, 4, 5, 6, 7, 8], [2, 3, 9, 10, 11, 12]]

Check out the documentation on Array#transpose, Array#map and Enumerable#reduce.

This tip was submitted by Haitham Mohammad.

1 note 0 comments

Mar 1 ’12

Quick shortcut to load a SQL file in Rails

You can easily load SQL files like this:

rails db < path_to_sql_file.sql # Rails 3 
script/dbconsole < path_to_sql_file.sql # Rails 2

6 notes 0 comments

Feb 28 ’12

Around Alias

You can write an Around Alias in three simple steps:

  1. You alias a method.
  2. You redefine it.
  3. You call the old method from the new method.

Example:

class String
  alias :orig_length :length

  def length
    "Length of string '#{self}' is: #{orig_length}"
  end  
end

"abc".length
#=> "Length of string 'abc' is: 3"

This tip was submitted by Nimesh Nikum.

2 notes 0 comments

Feb 21 ’12

Naming the Process

You can set the name of the current Ruby process, the one that you would see from the ps command for example.
Simply assign a string to the global variable $PROGRAM_NAME:

$PROGRAM_NAME = 'Hello from Rubyland!'
puts $0 # This is an alias for the same thing.

This is a great way for long running scripts or daemon processes to communicate status information to people who are looking in on them.

5.times do |i|
  $PROGRAM_NAME = "Ruby Quicktips Example: On iteration #{i}"
  sleep 5 # I'm really busy!!
end

Execute something like this in your terminal:

ps x | grep Quicktips

This tip was submitted by Jesse Storimer.

5 notes 0 comments

Feb 16 ’12

Making class methods private

This does not work:

class Foo
  private
  
  def self.bar
  end
end

Foo.bar will be public.
To make it private, you can use Module#private_class_method:

class Foo
  def self.bar
  end

  private_class_method :bar
end

…or define it differently:

class Foo
  class << self
    private
        
    def bar
    end
  end
end

This tip was submitted by two-bit-fool.

3 notes 0 comments

Feb 14 ’12

Clear your development logs automatically when they are too large

This snippet simply clears your logs when they are too large. Every time you run rails server or rails console it checks log sizes and clears the logs for you if necessary.

# config/initializers/clear_logs.rb

if Rails.env.development?
  MAX_LOG_SIZE = 2.megabytes
  
  logs = File.join(Rails.root, 'log', '*.log')
  if Dir[logs].any? {|log| File.size?(log).to_i > MAX_LOG_SIZE }
    $stdout.puts "Runing rake log:clear"
    `rake log:clear`
  end 
end

This tip was submitted by pahanix.

2 notes 0 comments

Feb 9 ’12

Quickly convert an Array to a Hash

As an example, let’s say you want to create an index of ActiveRecord objects by their id. Use the Hash constructor that accepts an Array of key-value pairs and do it in one line:

posts_by_id = Hash[*Post.all.map{ |p| [p.id, p] }.flatten]

This tip was submitted by http://Fullware.net/.

6 notes 0 comments

Feb 7 ’12

Initialize Objects with a Hash

If you want to initialize new instances of your class and specify values for its attributes directly, you can implement an initialize method with a lot of arguments. Or you can use a Hash - the Rails way:

my_puppy = Dog.new(:name => "Luke", :birthdate => Time.now)

You can do this by using a general initialize implementation:

module GeneralInit
  def initialize(*h)
    if h.length == 1 && h.first.kind_of?(Hash)
      h.first.each { |k,v| send("#{k}=",v) }
    end
  end
end

For every class that needs to take advantage of this, you just have to include GeneralInit. The initialize method will be available and work the way you expect it to.
It is still possible to create a new instance without arguments (Dog.new), or passing in a Hash with attribute/value pairs (as shown in the example above).

This tip was submitted by Rik Vanmechelen.

6 notes 0 comments