Flowdock

Notes posted to Ruby

RSS feed
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'
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
2 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 :)