2013-10-09 35 views
0

在我的Rails應用程序中,我需要一個包裝ActiveRecord對象並禁用其所有setter的類。其他方法應該委託給內部對象。委託所有方法但設置器

例子:

class Person < ActiveRecord::Base 
    attr_accessible :name, :age 
    def adult? 
    age >= 18 
    end 
end 

class PersonWrapper 
    def initialize(person) 
    @person = person 
    end 
end 

person = Person.new(name: "John", age: 12) 
wrapper = PersonWrapper.new(Person) 

wrapper.age # => 12 
wrapper.adult? # => false 
wrapper.age = 123 # error 

有任何方便的方式做到這一點,除了method_missing

回答

0
class Wrapper 
    def self.create(ar_model) 
    klass = Class.new 
    ar_model.attributes.each do |k, v| 
     klass.send(:define_method, k) { @obj[k] } 
    end 
    klass.send(:define_method, :initialize) {|obj| @obj = obj} 
    klass.new(ar_model) 
    end 
end 

使用

p = Person.first 
wrapper = Wrapper.create(p) 
wrapper.adult? # => false 
wrapper.age = 123 #method not defined 

可能不那麼容易的method_missing一樣方便,但它的工作原理

[編輯]

這樣意味着,如果被包裝的對象所沒有的一些屬性進行設置,那麼getters將不會被創建在包裝類中,如果你換行

ar_model.attributes.each do |k, v| 

這一個

ar_model.class.column_names.each do |k| 

那麼一個getter會爲每個列包裝的對象是否具有相應的屬性設置或不

1

如果你只是想阻止對數據庫的更新,你可以創建使用readonly!

person = Person.new(name: "John", age: 12) 
person.readonly! 
person.age = 123 #=> works 
person.save  #=> raises ActiveRecord::ReadOnlyRecord 

或者你可以freeze記錄:

person = Person.new(name: "John", age: 12) 
person.freeze 
person.age = 123 #=> raises RuntimeError: can't modify frozen Hash