0

I am using Ruby on Rails 3.2.9 and I would like to extend the framework with a custom validator located in a sub-directory of the lib/ directory. I implemented the following:

# lib/extension/rails/custom_validator.rb
module Extension
  module Rails
    class CustomValidator < ActiveModel::EachValidator
      # ...
    end
  end
end

After I restart the server I get the Unknown validator: 'CustomValidator' error. How can I solve the problem?


Note I: In the config/application.rb file I stated config.autoload_paths += %W(#{config.root}/lib).

Note II: If I put the custom_validator.rb file "directly under" the lib/ directory (that is, without "sub-directoring" the file) and I use the following code then it works.

# lib/custom_validator.rb
class CustomValidator < ActiveModel::EachValidator
  # ...
end
Backo
  • 18,291
  • 27
  • 103
  • 170

1 Answers1

0

Try to have a file in the lib folder named "extension.rb" with the following content

$:.unshift File.expand_path(File.dirname(__FILE__))

module Extension
    module Rails
        autoload :CustomValidator, "extension/rails/custom_validator"
    end
end

checkout http://www.rubyinside.com/ruby-techniques-revealed-autoload-1652.html and https://github.com/macournoyer/thin/blob/c8f4627bf046680abb85665f28ab926e36c931db/lib/thin.rb for how this technique is used.

The previous code assumes that you've written your validator like following

# lib/extension/rails/custom_validator.rb
module Extension
  module Rails
    class CustomValidator < ActiveModel::EachValidator
      # ...
    end
  end
end

And that you've included it in your model like the following

class MyModel
  validates_with Extension::Rails::CustomValidator
end

Another option would be to define the validator as follows

# lib/extension/rails/custom_validator.rb

class CustomValidator < ActiveModel::EachValidator
  # ...
end

and then add its directory to the load path of your application

# config/application.rb
config.autoload_paths += %W(#{config.root}/lib/extension/rails)

And in your model use the following to validate

class MyModel
  validates :my_property, :presence => true, :custom => true
end
shadysayed
  • 236
  • 2
  • 5
  • you may need to add the following to the beginning of the file. see edit. $:.unshift File.expand_path(File.dirname(__FILE__)) – shadysayed Dec 16 '12 at 16:16
  • What makes the `$:.unshift File.expand_path(File.dirname(__FILE__))` code? What is it intended for? However, even adding that code, I am still getting the `Unknown validator: 'CustomValidator'` error. It seems that the `extension.rb` file is never loaded... – Backo Dec 16 '12 at 18:07
  • This code adds the current folder to the load path. which you already did in application.rb but I thought it may help – shadysayed Dec 16 '12 at 19:05
  • Can you please post the code for the model (how do you include the validator in the model?) – shadysayed Dec 16 '12 at 19:06
  • I do *not* `include` the `CustomValidator` class in the model. It is inheriting from `ActiveModel::EachValidator` and I am using it as in the second example present in the [official documentation](http://guides.rubyonrails.org/active_record_validations_callbacks.html#custom-validators) related to Custom Validators. – Backo Dec 16 '12 at 21:56
  • *BTW*: I opened a [related question](http://stackoverflow.com/questions/13906040). – Backo Dec 16 '12 at 22:31
  • I see, so you use something like :custom => true in the validation line. In this case you will need to have your class in the global namespace and add the path of the custom_validator.rb in the load paths. see my edits – shadysayed Dec 17 '12 at 17:26
  • At this time, in order to accomplish the same as the `config.autoload_paths += %W(#{config.root}/lib/extension/rails)` statement, I am using the `require` method in a `config/inizializers.rb` file. What do you think about? What is the best choice between the two approaches? – Backo Dec 18 '12 at 00:56