Notes posted to Ruby

RSS feed
January 28, 2011 - (>= v1_8_7_72)
1 thank

Passing a block with methods

Code example

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

  def longitude
    -2
  end

  def with_address
    "with #{address}"
  end
end

g = Google.new("Some Addres")

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

Result

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

Includes the dot

Returns the extension including the ‘.’.

E.g.

Pathname("/path/to/file.rb").extname
#=> ".rb"
November 9, 2010
10 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

map_with_index

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.

e.g.

"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
rational_offset.to_i
#62
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

a.from(i)

It reads a lot better

August 5, 2010
0 thanks

Block_given?

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

array[n..-1]
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) 
  end
end

end
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
    else
      res[k.to_s] = self[k]
    end
  end
  return res
end

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
    else
      res[k.to_sym] = self[k]
    end
  end
  return res
end

end
June 3, 2010
0 thanks

Testing Net:HTTP connections

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

http://github.com/bblimke/webmock

May 19, 2010
0 thanks

Looking for "to the power of"?

If you’re trying to calculate 2 to the power of 2, the ^ method is not what you want. Try ** instead.

2^2  #=> 0
2^8  #=> 10
2**2 #=> 4
2**8 #=> 256
May 17, 2010
2 thanks

Add has_keys? method to Hash class

class Hash

def has_keys?(*_keys)
  (_keys - self.keys).empty?
end

end

h = {1=>‘a’,2=>‘b’}

h.has_keys?(1,2) #-> true

h.has_keys?(1,3) #-> false

May 5, 2010
0 thanks

Avoiding the "multiple values for a block parameter" warning

As pointed out below, you can also have optional parameters. But you will get something like “warning: multiple values for a block parameter (0 for 1)” if you omit them.

You can avoid those warnings by passing *args and picking the parameters yourself:

define_method :that_method do |*args|

  foo = args[0] || 'my default'
  # ...
end

Now the warning will be gone. Just make sure you fetch your parameters from *args and assign a default value (unless you want them to default to nil).

May 3, 2010 - (<= v1_8_7_72)
2 thanks

Changes self

This method changes the object/array the method is called on. For example:

a = ["a", "b", "c"]
b = ["x", "y", "z"]

a.concat(b)  #=> [a", "b", "c", "z", "y", "z"]
a #=> [a", "b", "c", "z", "y", "z"]

In this example the object A is modified, the method modifies the object, then returns the new object.

April 21, 2010
0 thanks

Mode Flags

RDONLY, TRUNC, etc… are defined in the File::Constants module which is include'd by IO and File.

IO.open fd, IO::RDONLY
File.open path, File::RDONLY

Though as pointed out above, they are interchangeable.

April 21, 2010
0 thanks

Errors Raised

Non IO errors (IOError) are contained in the Errno module. They are the same as those given in open(2), see:

http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html#ERRORS

Common Errors

  • Errno::ENOENT: No such file or directory

  • Errno::EACCES: Permission denied

  • Errno::EEXIST: File exists (i.e. IO::EXCL | IO::CREAT)

April 16, 2010
1 thank

Also behaves like File#expand_path

You can also use URI.join to resolve relative and absolute links:

URI.join('http://example.com/', '/example').to_s
# => "http://example.com/example"

URI.join('http://example.com/example', 'test').to_s
# => "http://example.com/test"

URI.join('http://example.com/example/', 'test').to_s
# => "http://example.com/example/test"

URI.join('http://example.com/example/foo', '../css').to_s
# => "http://example.com/css"
April 16, 2010
5 thanks

Require file from the same folder

If you want to require file from the same folder, the simplest way is

require File.expand_path('../file-to-require', __FILE__)

If your file is /lib/book.rb

File.expand_path('../page', '/lib/book.rb') => '/lib/page.rb'