2009-02-28 67 views
2

我正在Rails應用程序上開發一個ruby,我希望能夠在每次保存前在每個AR對象上執行一個方法。ActiveRecord中的圖層超類型(Rails)

我想我會創建一個層超類型是這樣的:

MyObject << DomainObject << ActiveRecord::Base 

,並把在domainObject的回調(before_save)與我的特殊方法(基本上去掉像「H1」的標籤從對象的字符串屬性)。

問題在於rails是在詢問domain_object表,這顯然沒有。

我的第二次嘗試,以猴補丁活動記錄,像這樣:

module ActiveRecord 
    class Base 
    def my_method .... end 
    end 
end 

,並將該lib文件夾下。

這不起作用,它告訴我my_method是未定義的。

任何想法?

回答

4

嘗試對您的域對象使用抽象類。

class DomainObject < ActiveRecord::Base 
    self.abstract_class = true 
    # your stuff goes here 
end 

使用抽象類,您創建的模型不能有對象(無法實例化),也沒有關聯的表。

從從嚴格非類型化的閱讀Rails: Where to put the 'other' files

文件中的lib Rails的啓動時不會加載。 Rails已經覆蓋了Class.const_missingModule.const_missing以根據類名動態加載文件。事實上,這正是Rails加載模型和控制器的方式。

所以將文件放在lib文件夾中,Rails啓動時不會運行,並且不會修補ActiveRecord :: Base。你可以將文件放在config/initializers,但我認爲有更好的選擇。

+0

感謝邁克,這正是我的意思是,任何想法,爲什麼的lib下「的monkeypatching」文件夾沒有工作?如果你可以用這個更新答案,我相信它會被接受,我會解決這個問題。再次感謝 – 2009-02-28 16:55:07

+0

一般來說,如果你有一個ActiveRecord :: Base的附加,你將它放在lib目錄中,並將其包含在environment.rb中。不過,我同意抽象類更好地解決你的問題。 – 2009-03-01 23:30:00

1

另一種方法,我在以前的作業中用於從模型中剝離HTML標籤的方法是創建一個插件。我們剝離了很多不僅僅是HTML標籤,但這裏是HTML剝離部分:

的初始化(供應商/插件/剝離器/ init.rb):

require 'active_record/stripper' 
ActiveRecord::Base.class_eval do 
    include ActiveRecord::Stripper 
end 

剝離代碼(供應商/插件/stripper/lib/active_record/stripper.rb):

module ActiveRecord 
    module Stripper 
    module ClassMethods 
     def strip_html(*args) 
     opts = args.extract_options! 
     self.strip_html_fields = args 
     before_validation :strip_html 
     end 
    end 

    module InstanceMethods 
     def strip_html 
     self.class.strip_html_fields.each{ |field| strip_html_field(field) } 
     end 
    private 
     def strip_html_field(field) 
     clean_attribute(field, /<\/?[^>]*>/, "") 
     end 
     def clean_attribute(field, regex, replacement) 
     self[field].gsub!(regex, replacement) rescue nil 
     end 
    end 

    def self.included(receiver) 
     receiver.class_inheritable_accessor :strip_html_fields 
     receiver.extend   ClassMethods 
     receiver.send :include, InstanceMethods 
    end 
    end 
end 

然後在您的MyObject類,你可以選擇通過調用剝去領域的html:

class MyObject < ActiveRecord::Base 
    strip_html :first_attr, :second_attr, :etc 
end 
1

已經給出的HTML剝離插件代碼將處理問題中提到的特定用法。一般來說,要將相同的代碼添加到許多類中,包括模塊都可以輕鬆完成此任務,而無需從一些公共基礎繼承任何東西,或者將任何方法添加到ActiveRecord本身。

module MyBeforeSave 
    def self.included(base) 
    base.before_save :before_save_tasks 
    end 

    def before_save_tasks 
    puts "in module before_save tasks" 
    end 
end 

class MyModel < ActiveRecord::Base 
    include MyBeforeSave 
end 

>> m = MyModel.new 
=> #<MyModel id: nil> 
>> m.save 
in module before_save tasks 
=> true 
0

我猴補丁的ActiveRecord :: Base和把文件中的配置/初始化:

class ActiveRecord::Base 

    before_create :some_method 

    def some_method 
    end 

end