Geplaatst door Michiel de Mare
do, 21 feb 2008 08:00:00 GMT
I always have an irb or rails console session open, and I love methods
to see what an object is capable of, but it certainly returns an exceptional amount of unsorted crap, especially in Rails.
Therefore, mymethods
:
class Object
def mymethods
(methods - Object.instance_methods).sort
end
end
(1..2).methods.size # => 150
(1..2).mymethods.size # => 46
Geplaatst in ruby, english, daily_method | 1 reactie
Geplaatst door Michiel de Mare
wo, 20 feb 2008 11:12:00 GMT
On June 5th the third edition of the RubyEnRails conference will take place in Amsterdam. Last year, about a third of the sessions were in English. It’s not yet possible to register, but we’re looking for speakers.
If you’re interested in giving a presentation about a cool Rails or Ruby subject, let us know.
Some suggestions:
- Ruby 1.9
- Experiences with Rails deployment
- Build a Facebook application in 45 minutes with Rails
- Tools for Rails – IDEs, editors, debuggers, etc.
Use the rubyenrails2008(ape)rubyenrails.nl email-address to apply.
Geplaatst in ruby on rails, events, english | Tags rer2008 | geen reacties
Geplaatst door Michiel de Mare
wo, 20 feb 2008 08:00:00 GMT
It took me a while before I discovered the accepted Ruby idiom to find the bigger of two values. I expected a method in Kernel
or perhaps in Comparable
. Instead, the Ruby Way is to create an array and ask the maximum value in the array:
[x,y].max
Well, it’s certainly short, but I don’t like it, for three reasons:
- You create an array to compare two integers? That has to be inefficient, right? Of course, worrying about efficiency is not The Ruby Way.
- I don’t like the name. When I say max it feels as if I’m declaring an upper bound, a maximum, when in fact, I’m declaring a lower bound, a minimum.
- By listing both values in the array, you’re placing them on equal footing, when often that’s not really the case. Often it’s more an afterthought: you’re saying: I want value foo (and by the way, it must be at least 7.25).
Hence,
at_most
and
at_least
:
total_time / total_tries.at_least(1)
Implementation too trivial to list.
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Michiel de Mare
di, 19 feb 2008 08:00:00 GMT
Hash
has an invert
-method, but it often happens that you’re dealing with a hash with arrays as values. Naturally, you don’t want arrays as keys – you want every element in the array to turn into a key, with an array of all original keys with that element as the value.
Simple example
{1 => [3,4]}.inv_multi
# => {3=>[1], 4=>[1]}
Complex example
{1 => [3,4,5,6], 2 => [3,4], 4 => 11}.inv_multi
# => {5=>[1], 11=>[4], 6=>[1], 3=>[1, 2], 4=>[1, 2]}
The method itself:
class Hash
def inv_multi
# there's inject! again. daily method #5
inject!({}) do |h,(k,v)| # Is this obvious? If not, say so!
# this lambda binds h and k.
l = lambda {|x| (h[x] ||= []) << k}
if Array === v
v.each(&l)
else # value doesn't have to be an array
l[v]
end
end
end
end
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Michiel de Mare
ma, 18 feb 2008 08:00:00 GMT
Ruby 1.9 has Object#tap
. Danny introduced Object#with
a long time ago. Then there’s Object#instance_eval
.
Do these methods have anything in common, except for the inscrutability of their names?
It turns out that they do. These methods fall in the family of methods that:
- Are defined for any
Object
- Take a block and always execute it once
- Don’t do anything else
So it may seem amazing that there are as much as three methods in this category. Actually, there’s even a fourth!
You see, even within these strict specs there are two decisions that we have to take.
- What do we return? The object itself? Or the result of the block?
- Within the block, what is
self
? Is it the object? Or is it unchanged (so we need to pass on the object as an argument)?
How do the methods we referred to earlier stack up?
tap
: returns result, same self in block
with
: return self, same self in block
instance_eval
: returns result, different self in block.
And the Missing Method:
switch
: returns self, different self in block.
Let’s see these methods in action!
Lees verder...
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Michiel de Mare
vr, 15 feb 2008 08:00:00 GMT
It’s Friday so we’ll keep it short.
[String,Symbol].each{|c|c.class_eval {alias +@ to_sym}}
Is it a Symbol? Is it a String? Who gives a damn!
hash[+key]
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Remco van 't Veer
do, 14 feb 2008 08:00:00 GMT
In an earlier daily method an alias is created for a class method. This is a bit tricky since the Module#alias_method
method only operates in instance methodes. Fortunately a class is an instance of Class
so we can use that instance as a context to use alias_method
.
To extend an object instance we use the class<<
notation. This adds a singleton/eigen/virtual/meta-class to the given instance which you can use to add methodes. Inside a class definition the self
object points to the instance of the class begin defined. This allows us the do the following:
class Foo
class << self
alias_method :neu, :new
end
end
This Foo
class can now be instanciated using neu
(note, new
is just a class method). But this class<<
stuff inside a class is a bit messy. I prefer using the following extension to Object
:
class Object
def self.alias_class_method(new_name, old_name)
meta = class << self; self; end
meta.send :alias_method, new_name, old_name
end
end
Now we can write:
class Foo
alias_class_method :neu, :new
end
For more information about eigenclasses see the discussion Nutter and Lam had on Ruby-core.
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Michiel de Mare
wo, 13 feb 2008 08:00:00 GMT
You all know
flatten
. Flatten takes an array and removes all structure from it. But sometimes you’ve got an array of arrays of arrays, and want to turn it into an array of arrays. What we need is a flatten-light:
mjoin
module Enumerable
def mjoin
inject!([]) {|memo,x| a.each {|x| memo << x}}
end
end
(read more about
inject!
).
When do you use this? Whenever you want to use map
but you don’t always want to return exactly one value, and some or all of the values are arrays (which means you can’t use flatten).
Does that sound exceedlingly rare? In fact, it is a very common structure. A table is an array of arrays, and a join is an operation which returns zero or more results per row. And this also explains the name! (join
, of course, is already taken – mjoin was inspired by this article).
I plan to talk more about using the table datastructure in the near future.
Geplaatst in ruby, english, daily_method | geen reacties
Geplaatst door Remco van 't Veer
di, 12 feb 2008 08:00:00 GMT
AR.find(..).each
Working with ActiveRecord it often bothers me I need to write each
after doing a find-all. I can give find
a block but is just ignored without any warning.
So today no new method but the removal of a method!
class ActiveRecord::Base
def self.find_with_block_sensitivity(*args)
r = find_without_block_sensitivity(*args)
[r].flatten.each {|v| yield v} if block_given?
r
end
class << self
alias_method :find_without_block_sensitivity, :find
alias_method :find, :find_with_block_sensitivity
end
end
Now, instead of:
Article.find(:all).each {|article| puts article.title}
we can write:
Article.find(:all) {|article| puts article.title}
Look ma! No each
! Also works for single object results.
Geplaatst in ruby, ruby on rails, english, daily_method | geen reacties
Geplaatst door Michiel de Mare
ma, 11 feb 2008 08:52:00 GMT
This is a Dutch blog, and therefore we love to quote Dutch computer scientists:
Elegance is not a dispensable luxury but a factor that decides between success and failure.
Edsgar Dijkstra
Seven pieces of Java code and the alternative in Ruby:
1. Short circuit with nil
Java
if(foo != null) {
bar(foo);
} else {
bar("");
}
Ruby
bar(foo || "")
Lees verder...
Geplaatst in ruby, english | 1 reactie