Notes posted to Ruby

RSS feed
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
0 thanks

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

October 11, 2010
0 thanks

output is buffered and will not appear until flush

Output is buffered on most operating systems. To override this behavior, force the stdout or other io to sync

STDOUT.sync = true
October 9, 2010
6 thanks

Be Advised

Also may convert original string into Jamaican.


"green moon".squeeze  #=> "gren mon"
October 4, 2010
1 thank

Bind the named method to the receiver

Binds the named method to the receiver, returning a Method object with access to the internals of the receiver, such as self and instance variables.

September 7, 2010 - (v1_8_6_287 - v1_8_7_72)
1 thank

To illustrate Date class let's calculate days between dates

Code example

date_from = Date.new(2010, 9, 11)
#<Date: 4910901/2,0,2299161>
date_till = Date.new(2010, 11, 12)
#<Date: 4911025/2,0,2299161>
rational_offset = (date_till - date_from)
#Rational62, 1
August 17, 2010
1 thank

Getting n..end in Rails

Nice one, henning. For anyone using Rails (ActiveSupport) a handy method called #from is also present.

[1, 2, 3, 4, 5].from(2) # => [3, 4, 5]

So our example would be


It reads a lot better

August 5, 2010
0 thanks


Kernel#block_given? can be used to check if yield would be able to call a block.

July 29, 2010
4 thanks

Getting (n..end) reloaded

You can do

June 25, 2010
0 thanks

can return nil

I was surprised to get nil back when the right hand side (RHS) was nil. (I was expecting an exception.)

>> "abc" <=> nil
=> nil

Looking at the source I find you’ll get nil back in several cases when the RHS isn’t a string.

  • If the RHS doesn’t implement to_str.

  • If the RHS doesn’t implement <=>.

Assuming the RHS does implement to_str and <=>, the code delegates to the RHS and negates the result:

return - (rhs <=> self)
June 25, 2010 - (v1_8_6_287 - v1_8_7_72)
0 thanks

Can operate for both key and value for Hash

If you need to process both key and value of the Hash:

>> {"a" => "aa", "b" => "bb", "c" => "cc"}.collect {|k,v| [k,k+v]}
=> [["a", "aaa"], ["b", "bbb"], ["c", "ccc"]]
June 23, 2010
2 thanks

Doesn't handle nested hashes

If you pass something like this:

http.set_form_data({:a => {:b => :c}})

it will completely mangle the value. So don’t use it.

June 17, 2010
0 thanks

writes the file to disk even if you pass a block

I was surprised to find that the local file is opened and written even if you pass the block. If you’re local working directory isn’t writeable or doesn’t have the space, you’re out of luck.

June 17, 2010
0 thanks

writes the file to disk even if you pass a block

I was surprised to find that the local file is opened and written even if you pass the block. If you’re local working directory isn’t writeable or doesn’t have the space, you’re out of luck.

June 13, 2010
0 thanks

Add requires!

Useful for methods that take options = {}

class Hash

def requires!(*params)
  params.each do |param| 
    raise ArgumentError.new("Missing required parameter: #{param}") unless self.has_key?(param) 

June 13, 2010
0 thanks

keys to/from symbols

There’s probably a more effecient way to do this…

class Hash

def keys_to_strings
  res = {}
  self.keys.each do |k|
    if self[k].is_a?(Hash)
      res[k.to_s] = self[k].keys_to_strings
      res[k.to_s] = self[k]
  return res

def keys_to_symbols
  res = {}
  self.keys.each do |k|
    if self[k].is_a?(Hash)
      res[k.to_sym] = self[k].keys_to_symbols
      res[k.to_sym] = self[k]
  return res

June 3, 2010
0 thanks

Testing Net:HTTP connections

You can use this excellent library to stub Net:HTTP connections in your automatic tests: