Redefining before_validation for an ActiveRecord model

Hi

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
end

with model:

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

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
end

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

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”
end

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
            end

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

‘#{value}’"
end
with_scope :find => (@find_option) do
orig_find_every(*args)
end
end
end
end
end
end

(I borrowed the code from the excellent HOWTO, see
http://www.railsforum.com/viewtopic.php?id=682

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’
end

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]
end
orig_before_validation
end

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
Wim

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
(http://www.axsguard.com)

Able NV: ond.nr 0457.938.087
RPR Mechelen