我有一个代表formula
的限制模型。字段formula
是在运行时评估的字符串。出于安全原因,无法从外部访问此字段,因此我试图覆盖访问者。
class Restriction < ActiveRecord::Base
belongs_to :indicator
RESTRICTION_TYPES = {
less_than: "IND<X",
greater_than: "X<IND",
between: "X<IND && IND<Y"
}
def evaluate(number)
f = formula.gsub("IND", "#{number}")
eval(f)
end
def create_formula(type_name, arg)
if(type_name == :between)
f = RESTRICTION_TYPES[:between].gsub("X", "#{arg[0]}").gsub("Y", "#{arg[1]}")
else
f = RESTRICTION_TYPES[type_name].gsub("X", "#{arg}")
end
formula = f
end
private
def formula= f
write_attribute(:formula, f)
end
def formula
read_attribute(:formula)
end
def [](value)
super[value]
end
def []=(key, value)
super[key] = value
end
end
在rails控制台中:
Loading development environment (Rails 4.0.0)
2.0.0p247 :001 > r = Restriction.new
=> #<Restriction id: nil, formula: nil, indicator_id: nil, created_at: nil, updated_at: nil, state: nil>
2.0.0p247 :002 > r.create_formula(:between, [1,2])
=> "1<IND && IND<2"
2.0.0p247 :003 > r.evaluate 1.5
NoMethodError: undefined method 'gsub' for nil:NilClass
2.0.0p247 :004 > r
=> #<Restriction id: nil, formula: nil>
formula
不会更改该值。我做错了什么?
PS:您可以看到我也覆盖了[](value)
和[]=(key, value)
。这是由于我的previous question
答案 0 :(得分:1)
Rails内部依赖于类似于哈希的访问方法来读取和写入属性。通过将它们设为私有,您希望仅限制对象内的[]和[] =的访问权限。但是你破坏了这个方法,因为你使用的是超级错误的方法。当调用super
时,你没有得到这个类的超级对象,而是超级方法,当前方法会覆盖。因此,改变它,它应该工作:
def [](value)
super(value)
end
def []=(key, value)
super(key, value)
end
P.S。:重写一种声明私有的方法在Ruby中是过度的。你可以简单地用
声明它是私有的private :[], []=