Notes posted to Ruby
RSS feedPassing 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
Includes the dot
Returns the extension including the ‘.’.
E.g.
Pathname("/path/to/file.rb").extname #=> ".rb"
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.
Will raise error on broken symlink
This method will raise Errno::ENOENT on a broken symlink. You should probably rescue it every time you call this method.
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"]
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
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
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.
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
Block_given?
Kernel#block_given? can be used to check if yield would be able to call a block.
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)
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"]]
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.
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.
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.
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
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
Testing Net:HTTP connections
You can use this excellent library to stub Net:HTTP connections in your automatic tests:
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
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
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).
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.
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.
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)
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"
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'