Notes posted to Ruby

RSS feed
November 16, 2011
1 thank

Change in clone for ActiveRecord objects in ruby-1.9.3

I noticed that cloning an active record object in ruby-1.9.3 and then changing an attribute on the original object will actually change the cloned object as well. This was not the case in ruby-1.9.2.

November 16, 2011
1 thank

Alternative definition

a.flat_map(&b) works exactly like a.map(&b).flatten!(1).

October 6, 2011
1 thank

Difference in the way returns are handled

Also, there is a difference in the way returns are handled from the Proc. A return from Proc.new returns from the enclosing method. Return in lambda-block acts like in regular method.

return example

def proc_return
  Proc.new { return "Proc.new"}.call
  return "proc_return method finished"

def lambda_return
  lambda { return "lambda" }.call
  return "lambda_return method finished"
puts proc_return
puts lambda_return
# => Proc.new
# => lambda_return method finished
October 4, 2011
1 thank

Unexpected rounding behavior

Both 2.5 and 1.5 are rounded to 2…

ree-1.8.7-2010.02 > sprintf("%.f", 0.5) 
=> "0" 
ree-1.8.7-2010.02 > sprintf("%.f", 1.5)
=> "2" 
ree-1.8.7-2010.02 > sprintf("%.f", 2.5)
=> "2" 
ree-1.8.7-2010.02 > sprintf("%.f", 3.5)
=> "4" 
ree-1.8.7-2010.02 > sprintf("%.f", 4.5)
=> "4" 

use round instead to get proper behavior

October 3, 2011 - (>= v1_9_1_378)
0 thanks

example will not work in 1.9+

Since 1.9 introduces native threads, we cannot assume the order of exectution and the example above is not thread safe and fails with a “deadlock detected (fatal)” error. Also Thread.pass is pointless in the context of native threads.

This will work as intended with native threads:

a = Thread.new { print "a"; Thread.stop; print "c" } 
sleep(0.1) until a.status == 'sleep'
print "b"
August 19, 2011
0 thanks

Alternative way to show relative paths from absolute globbing

An alternative to show relative paths is using the well known String#sub! method

base_dir = File.expand_path("my_dir") << "/" # don't miss adding "/"
files = Dir[File.join(base_dir, '**', '*.html.gz')]
p files.map {|f| f.sub!(base_dir,"")}
August 4, 2011
0 thanks

Tempfile extension


f = Tempfile.new(['graph','.json'])
July 30, 2011 - (>= v1_9_1_378)
0 thanks

now they are built-in

in ruby 1.9 and afterwards, the to_enum and enum_for(synonym for to_enum) methods are buil-in to the language. so there’s no need to require that any more.

July 15, 2011 - (v1_8_6_287 - v1_9_2_180)
1 thank

Dup vs Clone difference

As for me main difference between .dup and .clone , that first one doesn’t not freeze result object if initial object was frozen.

June 28, 2011 - (v1_9_2_180)
1 thank
June 13, 2011
0 thanks

Generalized Zip

My 5 cents.

I find trully useful this. Is a kind of generalized zip. You can combine 2 or more enumerables (arrays or others) of any size into a hash, array of arrays, .… The size of the result is the size of the bigest of the enumerables. For the shortests enumerables nil elements are used at the end.

# method compose
def compose(*enumerables)
  enumerables.map(&:size).max.times do
    for enumerable in enumerables
      tupla << enumerable.shift
    res << (block_given? ? yield(tupla) : tupla)

some examples:

en1= [1, 2, 3, 4]
en2= ['a', 'b', 'c', 'd', 'e']
en3= {:elem1 => "1", :elem2 => "2", :elem3 => "3"}

p compose en1.dup, en2.dup, en3.dup
p a1=compose(en2.dup, en1.dup) {|a,b| {a.to_sym => b}}

p a1.inject({}) {|ac,item| ac.merge item}
p a1.flatten

p a2=compose(en2.dup, en1.dup).flatten
p Hash[*a2]

p a3=compose(en2.dup, en3.dup).flatten

Their outputs are:

#[[1, "a", [:elem1, "1"]], [2, "b", [:elem2, "2"]], [3, "c", [:elem3, "3"]], [4, "d", nil], [nil, "e", nil]]
#[{:a=>1}, {:b=>2}, {:c=>3}, {:d=>4}, {:e=>nil}]
#{:b=>2, :d=>4, :e=>nil, :c=>3, :a=>1}
#[{:a=>1}, {:b=>2}, {:c=>3}, {:d=>4}, {:e=>nil}]
#["a", 1, "b", 2, "c", 3, "d", 4, "e", nil]
#{"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>nil}
#["a", :elem1, "1", "b", :elem2, "2", "c", :elem3, "3", "d", nil, "e", nil]
May 6, 2011
0 thanks

Using New

-rails new ProjectName -switch directories -git repo “git init”, then commit -add gems, bundle install -rails g scaffold TableName attribute:type attribute:type….. -authentication -add attribute_accessible/relationships/validations -get rid of index.html in public, set root “table#index” -rails g nifty:layout -rake db:migrate -git repo -rails s, see if works -change id’s to names in show and indexes -images go to public/images -partials are rendered in application.html.erb

April 28, 2011
1 thank

Backport from 1.9

Below is a backport of the Ruby 1.9 implementation (minus some encoding stuff). The main thing this provides you is the ability to say :foo => [‘bar’, ‘baz’] and have that turn into foo=bar&foo=baz (i.e. multiple values for the same key).

Just require into your project and use it like you are on 1.9.

module Net
  module HTTPHeader

    def set_form_data(params, sep = '&')
      query = URI.encode_www_form(params)
      query.gsub!(/&/, sep) if sep != '&'
      self.body = query
      self.content_type = 'application/x-www-form-urlencoded'
    alias form_data= set_form_data


module URI

  def self.encode_www_form(enum)
    enum.map do |k,v|
      if v.nil?
      elsif v.respond_to?(:to_ary)
        v.to_ary.map do |w|
          str = k.dup
          unless w.nil?
            str << '='
            str << w
        str = k.dup
        str << '='
        str << v

April 22, 2011
0 thanks

Remove non empty directories

To remove a non empty directory use FileUtils:

April 14, 2011
0 thanks


Chops the last character off a string.

> a = "12345"
> a.chop
=> "1234"
> a
=> "12345"
> a.chop!
=> "1234"
> a
=> "1234
April 4, 2011
2 thanks

Working with match captures

Let’s say you wanted to filter out passwords from:

s = "password=bob&password=jim&password=jane"

You’d do this:

r = /password\=([^\&]+)/
s.gsub!(r) { |m| m.gsub!($1, "[FILTERED]") }

Which would return

March 23, 2011
1 thank

Handling nested hashes and arrays

You can use this code to handle nested hashes and arrays. I’m not sure if it handles every case, and it could probably be refactored better, but it’s working quite well for us.

require 'active_support/core_ext/hash'

def normalize_params(params, key=nil)
  params = params.flatten_keys if params.is_a?(Hash)
  result = {}
  params.each do |k,v|
    case v
      when Hash
        result[k.to_s] = normalize_params(v)
      when Array
        v.each_with_index do |val,i|
          result["#{k.to_s}[#{i}]"] = val.to_s
        result[k.to_s] = v.to_s

# Adapted from http://snippets.dzone.com/posts/show/6776
class Hash
  def flatten_keys(newhash={}, keys=nil)
    self.each do |k, v|
      k = k.to_s
      keys2 = keys ? keys+"[#{k}]" : k
      if v.is_a?(Hash)
        v.flatten_keys(newhash, keys2)
        newhash[keys2] = v
March 3, 2011
1 thank

String#crypt uses your platform's native implementation

Which cipher types (specified through the salt argument) are available will depend on what your platform natively supports. It should be noted that OSX up to at last 10.6 only provides the regular DES cipher. On most Linux platforms, however, you should have access to the following:

ID  | Method
1   | MD5
2a  | Blowfish (not in mainline glibc; added in some
    | Linux distributions)
5   | SHA-256 (since glibc 2.7)
6   | SHA-512 (since glibc 2.7)

So on OSX, you might have:

ruby-1.9.2-p180 :001 > "password".crypt("$6$somesalt")
 => "$6FMi11BJFsAc" 

But on Linux, you’ll get:

irb(main):001:0> "password".crypt("$6$somesalt")
=> "$6$somesalt$A7P/0Yfu8RprY88D5T1n.xKT749BOn/IXBvmR1gXZzU7imsoTfZhCQ1916CB7WNX9eOOeSmBmmMrl5fQn9LAP1"

For more information on what your platform supports, see `man crypt`

March 3, 2011
0 thanks

Agree with Oleg

Yes, the only way round this seems to be to code e.g:

postArgs = { ‘table[field]’ => value, ‘table[f2]’ => v2 }

after the fashion of the browsers form definition.

This lets you do nested attributes as well, e.g: postargs[‘table[children_attributes[0][field]’] = value

March 3, 2011
1 thank

Perfectly applicable

@rkh You would be correct if this code had occurred in a subclass who’s parent method was being overridden.

However, defining the method in this manner is completely removing the old method - as if you had written code like this:

class MyClass
  def do_something
    puts "We're doing some stuff here"

  def do_something
    puts "The old do_something method no longer exists!"

# => "The old do_something method no longer exists!"

Of course this is non-sensical. But the idea is that you have either included a module, or monkey-patched an already existent class, and completely replaced the old method. super(*args) will not work

February 28, 2011
0 thanks


from ‘man recvfrom’

The flags argument to a recv() function is formed by or'ing one or more of the values:

MSG_OOB        process out-of-band data
MSG_PEEK       peek at incoming message
MSG_WAITALL    wait for full request or error

The MSG_OOB flag requests receipt of out-of-band data that would not be received in the normal data stream.  Some protocols place expedited data at the head of the
normal data queue, and thus this flag cannot be used with such protocols.  The MSG_PEEK flag causes the receive operation to return data from the beginning of the
receive queue without removing that data from the queue.  Thus, a subsequent receive call will return the same data.  The MSG_WAITALL flag requests that the opera-
tion block until the full request is satisfied.  However, the call may still return less data than requested if a signal is caught, an error or disconnect occurs, or
the next data to be received is of a different type than that returned.
February 22, 2011 - (v1_8_7_72)
0 thanks

counts the length of non-uncode characters.

jlength counts the non-unicode characters in a string to its actual length. Otherwise rails treat as 5 characters.

February 10, 2011
0 thanks

Eliminates Double Slashes

Also eliminates inadvertent double slashes:

path = '/uploads/art/'
file = '/pic.jpg'
File.join(path, file) # => '/uploads/art/pic.jpg'
January 28, 2011 - (>= v1_8_7_72)
1 thank

Passing a block with methods

Code example

Google = Struct.new(:address) do
  def latitude

  def longitude

  def with_address
    "with #{address}"

g = Google.new("Some Addres")

puts g.address
puts g.latitude
puts g.longitude
puts g.with_address


# >> Some Addres
# >> -1
# >> -2
# >> with Some Addres
November 24, 2010
0 thanks

Includes the dot

Returns the extension including the ‘.’.


#=> ".rb"
November 9, 2010
9 thanks

NOT Equivalent to Array#reject!

@tadman is wrong. There is a difference and, trust me, it can bite:

1.9.2 > [1,2,3,4].delete_if {|x| x > 10}
 => [1, 2, 3, 4] 
1.9.2 > [1,2,3,4].reject! {|x| x > 10}
 => nil 

That is, if reject! hasn’t rejected anything, it returns nil.

October 28, 2010
0 thanks


Of course such a method does not exist, however we can simulate it easily

%w(a b c).to_enum(:each_with_index).map{|a,i| "#{a}, #{i}"}
=> ["a, 0", "b, 1", "c, 2"]
October 11, 2010
0 thanks

Useful for mocking out IO methods like #gets and #puts

This class is helpful when testing certain classes of software libraries that are dependent on console input and output, similar to some testing uses of Java’s StringBuffer