Good notes posted to Ruby

RSS feed
October 9, 2008
3 thanks

Works with URLs too!

You can use it for web urls as well:

  path, file = File.split('/uploads/art/2869-speaking-of-pic.jpg')

  p path # => "/uploads/art"

  p file # => "2869-speaking-of-pic.jpg"

And you can also use join, to merge url back from the components:

  path = File.join(["/uploads/art", "2869-speaking-of-pic.jpg"])

  p path # => "/uploads/art/2869-speaking-of-pic.jpg"

Using #join and #split for operations on files and path parts of the URLs is generally better than simply joining/splitting strings by ’/’ symbol. Mostly because of normalization:

  File.split('//tmp///someimage.jpg') # => ["/tmp", "someimage.jpg"]

  '//tmp///someimage.jpg'.split('/') # => ["", "", "tmp", "", "", "someimage.jpg"]

Same thing happens with join.

September 12, 2008
17 thanks

Readable strftime

%a - The abbreviated weekday name (``Sun’’)

%A - The full weekday name (``Sunday’’)

%b - The abbreviated month name (``Jan’’)

%B - The full month name (``January’’)

%c - The preferred local date and time representation

%d - Day of the month (01..31) %H - Hour of the day, 24-hour clock (00..23)

%I - Hour of the day, 12-hour clock (01..12)

%j - Day of the year (001..366)

%m - Month of the year (01..12) %M - Minute of the hour (00..59)

%p - Meridian indicator (``AM’‘ or ``PM’’)

%S - Second of the minute (00..60)

%U - Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)

%W - Week number of the current year, starting with the first Monday as the first day of the first week (00..53)

%w - Day of the week (Sunday is 0, 0..6)

%x - Preferred representation for the date alone, no time

%X - Preferred representation for the time alone, no date

%y - Year without a century (00..99) %Y - Year with century

%Z - Time zone name %% - Literal ``%’’ character t = Time.now t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003" t.strftime("at %I:%M%p") #=> "at 08:56AM"

August 17, 2008
4 thanks

Re: Convert an Array of Arrays to a Hash using inject

If you’re sure you have a two-level array (no other arrays inside the pairs) and exactly two items in each pair, then it’s faster and shorter to use this:

  array = [['A', 'a'], ['B', 'b'], ['C', 'c']]
  hash = Hash[*array.flatten]

For more than two-level deep arrays this will give the wrong result or even an error (for some inputs).

  array = [['A', 'a'], ['B', 'b'], ['C', ['a', 'b', 'c']]]
  hash = Hash[*array.flatten]
  # => {"A"=>"a", "B"=>"b", "C"=>"a", "b"=>"c"}

But if you’re running Ruby 1.8.7 or greater you can pass an argument to Array#flatten and have it flatten only one level deep:

  # on Ruby 1.8.7+
  hash = Hash[*array.flatten(1)]
  # => {"A"=>"a", "B"=>"b", "C"=>["a", "b", "c"]}
August 17, 2008
3 thanks

Regexes with groups and split

When you use a Regex with capture groups, all capture groups are included in the results (interleaved with the "real" results) but they do not count for the limit argument.

Examples:

  "abc.,cde.,efg.,ghi".split(/.(,)/)
  => ["abc", ",", "cde", ",", "efg", ",", "ghi"]
  "abc.,cde.,efg.,ghi".split(/(.)(,)/)
  => ["abc", ".", ",", "cde", ".", ",", "efg", ".", ",", "ghi"]
  "abc.,cde.,efg.,ghi".split(/(.(,))/)
  => ["abc", ".,", ",", "cde", ".,", ",", "efg", ".,", ",", "ghi"]
  "abc.,cde.,efg.,ghi".split(/(.(,))/, 2)
  => ["abc", ".,", ",", "cde.,efg.,ghi"]
  "abc.,cde.,efg.,ghi".split(/(.(,))/, 3)
  => ["abc", ".,", ",", "cde", ".,", ",", "efg.,ghi"]
August 15, 2008
4 thanks

Cheking if a number is prime?

It’s a class for generating an enumerator for prime numbers and traversing over them.

It’s really slow and will be replaced in ruby 1.9 with a faster one.

Note: if you just want to test whether a number is prime or not, you can use this piece of code:

  class Fixnum
    def prime?
      ('1' * self) !~ /^1?$|^(11+?)\1+$/
    end
  end

  10.prime?
August 15, 2008
3 thanks

Optional Argument for detect/find [Not Documented]

detect/find’s optional argument lets you specify a proc or lambda whose return value will be the result in cases where no object in the collection matches the criteria.

  classic_rock_bands = ["AC/DC", "Black Sabbath","Queen", "Ted Nugent and the Amboy Dukes","Scorpions", "Van Halen"]
  default_band = Proc.new {"ABBA"}
  classic_rock_bands.find(default_band) {|band| band > "Van Halen"}
  => "ABBA"

or

  random_band = lambda do
    fallback_bands = ["Britney Spears", "Christina Aguilera", "Ashlee Simpson"]
    fallback_bands[rand(fallback_bands.size)]
  end
  classic_rock_bands.find(random_band) {|band| band > "Van Halen"}
  => "Britney Spears"
August 14, 2008 - (v1_8_6_287)
6 thanks

Convert an Array to a Hash

The Hash.[] method converts an even number of parameters to a Hash. (The Hash[] method depends on the Hash class, but don’t confuse the method with the class itself). For example:

  Hash['A', 'a', 'B', 'b']
  # => {"A"=>"a", "B"=>"b"}

You can convert an array to a hash using the Hash[] method:

  array = ['A', 'a', 'B', 'b', 'C', 'c']
  hash = Hash[*array]
  # => {"A"=>"a", "B"=>"b", "C"=>"c"}

The * (splat) operator converts the array into an argument list, as expected by Hash[].

You can similarly convert an array of arrays to a Hash, by adding flatten:

  array = [['A', 'a'], ['B', 'b'], ['C', 'c']]
  hash = Hash[*array.flatten]
  # => {"A"=>"a", "B"=>"b", "C"=>"c"}

This also comes in handy when you have a list of words that you want to convert to a Hash:

  Hash[*%w(
    A a
    B b
    C c
  )]
  # => {"A"=>"a", "B"=>"b", "C"=>"c"}
August 14, 2008
4 thanks

Convert an Array of Arrays to a Hash using inject

Converting an array of arrays to a hash using inject:

  array = [['A', 'a'], ['B', 'b'], ['C', 'c']]

  hash = array.inject({}) do |memo, values|
    memo[values.first] = values.last
    memo
  end

  hash
  # => {'A' => 'a', 'B' => 'b', 'C' => 'c'}