0

我有一个 Restriction 模型,它代表一个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)and []=(key, value)。这是由于我之前的问题

4

1 回答 1

1

Rails 内部依赖于类似哈希的访问方法来读取和写入属性。通过将它们设为私有,您希望将 [] 和 []= 的访问限制为仅在对象内部。但是您破坏了该方法,因为您使用了 super 错误的方法。调用时super,您获取的不是此类的超级对象,而是超级方法,当前方法会覆盖。因此像这样改变它,它应该可以工作:

def [](value)
  super(value)
end

def []=(key, value)
  super(key, value)
end

PS:重写一个声明私有的方法在 Ruby 中是矫枉过正的。您可以简单地将其声明为私有

private :[], []=
于 2013-08-05T14:51:34.567 回答