Notes posted to Ruby

RSS feed
April 8, 2010
2 thanks

Bad example

Note that it would be better to avoid the alias_method line in the example and just call super.

April 1, 2010
3 thanks

Doesn't return nil on empty array when param is given

This does not return nil if the array is empty and n is given.

[].shift(2) # => []

a = []
a.shift(2) # => []
a # => []
March 31, 2010
3 thanks

Interpolating

Note that to interpolate, the sequences must be inside single quotes:

# replace /ll/ with itself
'hello'.gsub(/ll/, '\0') # returns 'hello'
'hello'.gsub(/ll/, "\0") # returns 'he\000o'
March 28, 2010
0 thanks

at_exit in sintra

in main.rb of sinatra:

at_exit { Application.run! if $!.nil? && Application.run? }
March 25, 2010
0 thanks

RE: Replacing with "\" and match — a simple solution

Thanks. No, I am not trying to quote for a regex. It was mostly an approach thing since I came into contact with the behavior previously when I played around. After doing some tests, I figured I should spare any other adventurers that part. :-)

March 24, 2010
0 thanks

Time.now in UTC

A quick way to get the current time in UTC is:

Time.new.utc # => Wed Mar 24 14:38:19 UTC 2010
March 18, 2010
3 thanks

collect_with_index

Use Object#enum_for if you need to collect with index:

require 'enumerator'

['a', 'b', 'c'].enum_for(:each_with_index).collect do |item, index| 
  "#{index}: #{item}" 
end

See also: Enumerable#each_with_index

March 18, 2010 - (v1_8_6_287 - v1_8_7_72)
0 thanks

collect_with_index

Use Object#enum_for if you need to collect with index:

require 'enumerator'

%w{foo bar}.enum_for(:each_with_index).collect do |item, index| 
  "#{index}: #{item}" 
end

See also: Enumerable#each_with_index

March 17, 2010
0 thanks

Create new Hash as subset of another a different way

or

only keys

old_hash = { :a => 'A', :b => 'B', :c => 'C', :d => 'D', :e => 'E', :f => 'F' }
only_keys = [ :a, :c, :f ]
new_hash = old_hash.delete_if { |k, v| !only_keys.include? k }

only values

old_hash = { :a => 'A', :b => 'B', :c => 'C', :d => 'D', :e => 'E', :f => 'F' }
only_values = [ 'A', 'D', 'G' ]
new_hash = old_hash.delete_if { |k, v| !only_values.include? v }

there are many ways to skin a cat :)

March 17, 2010 - (>= v1_8_7_72)
0 thanks

Create new Hash as subset of another

old_hash = {:a=>‘A’,:b=>‘B’,:c=>‘C’,:d=>‘D’,:e=>‘E’,:f=>‘F’}

only_keys = [:a,:c,:f]

new_hash = Hash[*old_hash.find_all{|k,v| only_keys.member?(k)}.flatten]

# => {:a=>“A”, :c=>“C”, :f=>“F”}

or for values

only_vals = [‘A’,‘D’,‘G’]

new_hash = Hash[*old_hash.find_all{|k,v| only_vals.member?(v)}.flatten]

# => {:a=>“A”, :d=>“D”}

March 16, 2010 - (v1_8_6_287 - v1_8_7_72)
0 thanks

Another Example

Delete all files in log

require 'FileUtils'
Dir["log/*"].each{|file| FileUtils.rm file}
March 12, 2010
0 thanks

Complete Formatting Codes

%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

%C - Century (20 in 2009)

%d - Day of the month (01..31)

%D - Date (%m/%d/%y)

%e - Day of the month, blank-padded ( 1..31)

%F - Equivalent to %Y-%m-%d (the ISO 8601 date format)

%h - Equivalent to %b

%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)

%k - hour, 24-hour clock, blank-padded ( 0..23)

%l - hour, 12-hour clock, blank-padded ( 0..12)

%L - Millisecond of the second (000..999)

%m - Month of the year (01..12)

%M - Minute of the hour (00..59)

%n - Newline (n)

%N - Fractional seconds digits, default is 9 digits (nanosecond)

  • %3N millisecond (3 digits)

  • %6N microsecond (6 digits)

  • %9N nanosecond (9 digits)

%p - Meridian indicator (“AM” or “PM”)

%P - Meridian indicator (“am” or “pm”)

%r - time, 12-hour (same as %I:%M:%S %p)

%R - time, 24-hour (%H:%M)

%s - Number of seconds since 1970-01-01 00:00:00 UTC.

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

%t - Tab character (t)

%T - time, 24-hour (%H:%M:%S)

%u - Day of the week as a decimal, Monday being 1. (1..7)

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

%v - VMS date (%e-%b-%Y)

%V - Week number of year according to ISO 8601 (01..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 as hour offset from UTC (e.g. +0900)

%Z - Time zone name

%% - Literal “%” character

t = Time.now                        #=> 2007-11-19 08:37:48 -0600
t.strftime("Printed on %m/%d/%Y")   #=> "Printed on 11/19/2007"
t.strftime("at %I:%M%p")            #=> "at 08:37AM"
March 12, 2010
3 thanks

Complete Formatting Codes

NOTE: Some of these seem only to work for DateTime (e.g. %L, %N)

%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

%C - Century (20 in 2009)

%d - Day of the month (01..31)

%D - Date (%m/%d/%y)

%e - Day of the month, blank-padded ( 1..31)

%F - Equivalent to %Y-%m-%d (the ISO 8601 date format)

%h - Equivalent to %b

%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)

%k - hour, 24-hour clock, blank-padded ( 0..23)

%l - hour, 12-hour clock, blank-padded ( 0..12)

%L - Millisecond of the second (000..999)

%m - Month of the year (01..12)

%M - Minute of the hour (00..59)

%n - Newline (n)

%N - Fractional seconds digits, default is 9 digits (nanosecond)

  • %3N millisecond (3 digits)

  • %6N microsecond (6 digits)

  • %9N nanosecond (9 digits)

%p - Meridian indicator (“AM” or “PM”)

%P - Meridian indicator (“am” or “pm”)

%r - time, 12-hour (same as %I:%M:%S %p)

%R - time, 24-hour (%H:%M)

%s - Number of seconds since 1970-01-01 00:00:00 UTC.

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

%t - Tab character (t)

%T - time, 24-hour (%H:%M:%S)

%u - Day of the week as a decimal, Monday being 1. (1..7)

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

%v - VMS date (%e-%b-%Y)

%V - Week number of year according to ISO 8601 (01..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 as hour offset from UTC (e.g. +0900)

%Z - Time zone name

%% - Literal “%” character

t = Time.now                        #=> 2007-11-19 08:37:48 -0600
t.strftime("Printed on %m/%d/%Y")   #=> "Printed on 11/19/2007"
t.strftime("at %I:%M%p")            #=> "at 08:37AM"
March 11, 2010
0 thanks

Use message param

The message param is invaluable in case test fails – if you use it to display relevant info, you will find out what went wrong much faster.

Reworking the silly example above:

assert some_list.include?(5)

will only tell you that

<false> is not true.

which isn’t terribly helpful, is it? But if you use message like that:

assert some_list.include?(5), "some_list = #{some_list.inspect}"

the output will be:

some_list = [1, 2].
<false> is not true.

which in most cases should give you strong hints as to why the test failed.

March 8, 2010
0 thanks

Eagerness

Check out this simple example:

"Hello Ruby friend".sub(/^(.*)e/,  'X')  # => "Xnd"
"Hello Ruby friend".sub(/^(.*?)e/, 'X')  # => "Xllo Ruby friend"

The question mark turns the dotstar into non-eager mode which means it will halt on the first subsequent “e” rather than the last one. This comes in handy e.g. for Cucumber step definitions.

Okay, but not really nice:

/^I am using rvm "([^\"]*)" with gemset "(.*)"$/

Much more readable and consistent equivalent to the above:

/^I am using rvm "(.*?)" with gemset "(.*?)"$/
March 3, 2010
3 thanks

Deprecated in 1.9.x!

Use FileUtils::copy instead. It is also in 1.8.x, FileUtils, so call that one instead.

March 3, 2010 - (>= v1_8_6_287)
4 thanks

makedirs(path) to create file path

mkdir will only create a single directory on an existing path. If you want to create a full path, like the `mkdir -p /full/path` command, use the makedirs method.

1.8: File.makedirs(path) 1.9: FileUtils.makedirs(path)

February 19, 2010
8 thanks

Hash#except

Note that the ActiveSupport library provides the except and except! methods, which return the Hash minus the given keys. So you don’t need to write your own wrapper if you happen to be using Rails or ActiveSupport as a stand-alone library:

http://apidock.com/rails/ActiveSupport/CoreExtensions/Hash/Except/except

February 16, 2010
0 thanks

Re: POST DATA

The ampersand is more common, but the W3C recommends that all web servers support semicolon separators in the place of ampersand separators:

http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.2.2

February 12, 2010
0 thanks

Example

Delete all files in log

require 'FileUtils'
FileUtils.rm_rf(Dir.glob("log/*"))
February 11, 2010 - (v1_8_6_287 - v1_8_7_72)
1 thank

Using Unshift with Load Path's

Using unshift on your load path’s for Rails, Sinatra, etc, is a good way of ensuring that the file your including is going to be first.

Example

vendor = File.join(File.dirname(__FILE__), 'vendor')
$LOAD_PATH.unshift File.expand_path(File.join(vendor, 'ultraviolet-0.10.5',  'lib'))
February 11, 2010 - (v1_8_7_72)
0 thanks

Odd Number of padding characters

In the case of an odd number of empty spaces in a length, Ruby will append the extra character to the right-hand side of the string.

Example:

irb(main):002:0> "Hello".center(10,"-")
=> "--Hello---"
February 11, 2010 - (v1_8_6_287 - v1_8_7_72)
0 thanks

Clarification of argument

The description should read:

The argument is the salt string, which must be at least two characters long, each character drawn from [a-zA-Z0-9./].

February 5, 2010
3 thanks

Rmoving preceding 0's

In most *nix system, adding a - after the % will remove preceding 0s.

So %-d for a single digit day, or %-I for a single digit hour, etc.

February 4, 2010
1 thank

Warning! Be aware of Active Record TimeZone

With the timezone support introduced in Rails 2.1 the idea is that all dates in the database are stored in UTC and all dates in Ruby are in a local timezone.

Time.zone.now == Time.now # => false

http://marklunds.com/articles/one/402

January 27, 2010
1 thank

File name without the extension

To get the file name without the extension you can use File.extname in combination with File.basename

File.basename("test.rb", File.extname("test.rb"))             #=> "test"
File.basename("a/b/d/test.rb", File.extname("a/b/d/test.rb")) #=> "test"
File.basename("test", File.extname("test"))                   #=> "test"
File.basename(".profile", File.extname(".profile"))           #=> ".profile"
January 27, 2010
3 thanks
January 25, 2010
2 thanks

custom uniq method

Build hash from elements of your Array using attribute as key and the element as value and return values of Hash:

Hash[*ary.map {|obj| [obj.name, obj]}.flatten].values
January 22, 2010
1 thank

Interesting usage for polymorphic asset model :)

…to automatically define default scopes of inherited classes.

 class Asset < ActiveRecord::Base

  belongs_to :resource, :polymorphic => true
  before_save :set_asset_type

  def set_asset_type
   self.asset_type = self.class.name
  end

  def self.inherited(subclass)
    super
    subclass.send(:default_scope, :conditions => "asset_type='#{subclass.name}'")
  end
end
January 19, 2010
2 thanks

Argument Accepted

Accepts a single argument record_separator which is the character or string to chomp.

Why isn’t this shown in the method def at the top?