Redefining before_validation for an ActiveRecord model


I’m struggling more then a day now to try to write a simple plugin.

Let me explain what the plugin should do.
Consider a table called categories that looks like:

create_table :categories do |t|
t.column :id, :integer
t.column :categorizable_type, :string, :null => false
t.column :categorizable_id, :integer, :null => false,
:references => nil
t.column :category_name, :integer, :null => false

with model:

class Category < ActiveRecord::Base
belongs_to :categorizable, :polymorphic => true
validates_presence_of :categorizable_type, :categorizable_id

Then for example a product is categorizable, table and model of product
look like this:

create_table :products do |t|
t.column :id, :integer
t.column :code, :string

class Product < ActiveRecord::Base
has_many :categories, :as => :categorizable

So products are categorizable. Now I want to define a model
product_categories that contains all categories for products.

The definition of product_categories is:
class ProductCategory < Category
set_scope :categorizable_type, “Product”

Notice the ‘set_scope’ definition. This is the plugin I am writing
(called ScopedModel) and the idea is that when a model gets the
set_scope definition, automatically the categorizable_type should be on
‘Product’ for all manipulations.
For example:

ProductCategory.find(:all) should result in:

select * from categories where categorizable_type=‘Product’

ProductCategory.create!(category_name => ‘some_name’) should result in a
record being created where categorizable_type has value ‘Product’.

So all operations on ProductCategory should result in making sure that
everything is qualified with 'categorizable_type = ‘Product’.
Until now I have been able to make it work for find, but I can’t let it
work for create, update ,…

My working plugin code until now is:

ActiveRecord::Base.send :include, ScopedModel

module ScopedModel
def self.included(base)
base.class_eval do
class << self
alias_method :orig_find_every, :find_every

            def set_scope(attribute,value)
                @model_scope ||= {}
                @model_scope[attribute] = value

            # redefine find
            def find_every(*args)
                @find_option =
                @model_scope ||= {}
                @model_scope.each_key do |attribute|
                    value = @model_scope[attribute]
                    @find_option[:conditions] = "#{attribute} =

with_scope :find => (@find_option) do

(I borrowed the code from the excellent HOWTO, see

So the find method automatically adds the scope qualification by adding
it to the find of the class’s singleton class.
For the create, update, I want to use the ‘before_validation’ method. If
I put next in my ProductCategory model:

def before_validation
self.categorizable_type = ‘Product’

Problem is that I should be able to define this before_validation in the
plugin in the singleton class for product_category.
And I tried everything but nothing works. The code in the plugin should
be something like:

alias_method :orig_before_validation, :before_validation
def before_validation
@model_scope ||= {}
@model_scope.each_key do |attribute|
self.attribute = @model_scope[attribute]

Problem is that before_validation is mixed_in in ActiveRecord::Base and
also that it should work on an instance and not at class_level, while my
definition of set_scope is at (singleton) class level,

Hope that anyone can shed some light on this problem.

Thanks and Regards

NEW on aXs GUARD: SSL VPN !! (contact your reseller for more info)

aXs GUARD has completed security and anti-virus checks on this e-mail

Able NV: 0457.938.087
RPR Mechelen

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs