Good notes posted by Oleg
RSS feed
define_method with parameters
Just to be clear, you can do this:
define_method(:my_method) do |foo, bar| # or even |*args| # do something end
This means same as:
def my_method(foo, bar) # do something end
If you want to define method with parameters that have default values, you need to get a bit more creative and do something like this:
define_method(:my_method) do |foo, bar| bar ||= {} # do something end

cattr_accessor_with_default
Class attribute assessors are neat if you want to set up modifiable constant-like varibles. This is how you’d normally set it up:
module MyPlugin class Conf @@awesome_level = 'huge' cattr_accessor :awesome_level end end
Then you can call and modify it like this:
>> MyPlugin::Conf.awesome_level => 'huge' >> MyPlugin::Conf.awesome_level = 'massive' >> MyPlugin::Conf.awesome_level => 'massive'
If you have a pile of those accessors I’d do something like this (there might be a better way, but it works):
module MyPlugin class Conf def self.cattr_accessor_with_default(name, value = nil) cattr_accessor name self.send("#{name}=", value) if value end cattr_accessor_with_default :awesome_level, 'huge' cattr_accessor_with_default :speed_level, 'insane' cattr_accessor_with_default :indifferent_level cattr_accessor_with_default :craziness_level, 'nuts' end end
This way you declare accessor and it’s optional default value on the same line

Handy shorthand for array manipulation
You may write something like this:
>> ['a', 'b', 'c'].collect{|letter| letter.capitalize} => ["A", "B", "C"]
But it looks so much nicer this way:
>> ['a', 'b', 'c'].collect(&:capitalize) => ["A", "B", "C"]

HTML entities in options
Unfortunately everything is escaped with ERB::Util#html_escape. Your only option is either manually construct options or compeletely overwrite this method.

Array clustering
Sometimes you don’t want to mangle sequence of an array and just want to group adjacent values. Here’s a nice method to do so (drop it in your initializers directory or something):
module Enumerable # clumps adjacent elements together # >> [2,2,2,3,3,4,2,2,1].cluster{|x| x} # => [[2, 2, 2], [3, 3], [4], [2, 2], [1]] def cluster cluster = [] each do |element| if cluster.last && yield(cluster.last.last) == yield(element) cluster.last << element else cluster << [element] end end cluster end end
Similarly you can do the clustering on more complex items. For instance you want to cluster Documents on creation date and their type:
Document.all.cluster{|document| [document.created_on, document.type]}

Take care when writing regex
When you want to validate a field for a continuous string you’d probably write something like this (if it’s really early in the morning and you didn’t have your coffee yet):
validates_format_of :something => /\w/
At the first sight it looks like it’s working because something = “blahblahblah” is valid. However, so is this: something = “blah meh 55”. It’s just that your regex matched a substring of the value and not the whole thing. The proper regex you’re looking for is actually:
validates_format_of :something => /^\w$/

String#match will match single token only
>> s = “{{person}} ate {{thing}}”
> “{{person}} ate {{thing}}”
>> r = /{{(.*?)}}/
> {{}}
>> s.match®.captures
> [“person”]
Using String#scan pulls out all tokens you were searching for:
>> s.scan®.flatten
> [“person”, “thing”]

For those who is looking for lost country_select
country_select lives on as a plugin that can be acquired from here: http://github.com/rails/country_select/tree/master