views:

34

answers:

1

I have the following validation in a model:

validates_length_of :description,
  :minimum => 2, :on => :save,
  :message => "must be at least 2 words",
  :tokenizer => lambda {|text| text.scan(/\w+/)}

And this works fine. When I add a second field to the model that needs to be validated by number of words, I declare

tokenize_by_words = lambda {|text| text.scan(/\w+/)}

at the top of the model, and use

:tokenizer => tokenize_by_words

This also works fine, and keeps everything DRY. However, it all falls apart when I need to use the same tokenizer across multiple models. If I create config/initializers/tokenizers.rb thus:

class ActiveRecord::Base
  tokenize_by_words = lambda {|text| text.scan(/\w+/)}
end

and remove the definitions in the models, I get /Library/Ruby/Gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1959:in 'method_missing': undefined local variable or method 'tokenize_by_words' for #<Class:0x10357e988> (NameError)

Using an instance variable or replacing the whole thing with a method doesn't work either.

I'm sure there's something blindingly obvious I'm missing, but the only documentation I can find on :tokenizer doesn't really consider DRY-ness :(

A: 

You should define the tokenizer as a method, i.e.

class ActiveRecord::Base
  def foo(text)
    text.scan(/\w+/)
  end
end

Now use this method symbol as the value for :tokenizer attribute.

validates_length_of :description,
  :minimum => 2, :on => :save,
  :message => "must be at least 2 words",
  :tokenizer => :foo
KandadaBoggu
Thanks — unfortunately I now get this when I run the specfile for the model:NoMethodError in 'GbgSymbols should have a description of at least 2 words'undefined method `call' for :tokenize_by_words:Symbolwhich is the same as if I haven't defined the tokenizer at all! The config/initializers directory is the right place for the definition, isn't it?
John Yeates
It should work. I have verified this. Can you try to put the method in one of the models(instead of ActiveRecord::Base) and see if it works. If it does then there might be a issue in the way in which you are adding this method to ActiveRecord::Base class. Read this thread to get information about extending ActiveRecord: http://stackoverflow.com/questions/2328984/rails-extending-activerecordbase
KandadaBoggu