在我的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 :(得分: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
答案 1 :(得分: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方便,但它可以正常工作
[编辑]
这种方式意味着如果包装的对象没有设置某些属性,那么如果你交换行就不会在包装类中创建getter
ar_model.attributes.each do |k, v|
这个
ar_model.class.column_names.each do |k|
然后将为每个列创建一个getter,无论包装对象是否具有相应的属性集