如何覆盖rails 3.2.12中实例的方法?

时间:2013-03-31 22:07:05

标签: ruby-on-rails ruby singleton

在我们的rails 3.2.12应用中,我们希望override methodinstance并使其返回为空。理想情况下,我们可以为应用中的每个generic overriding method定义一个model

例如,@projectProject模型的实例,phone是列名。在方法覆盖之后,我们希望@project.phone在运行时返回空,而不是列的值。如果应用中有另一个模型customer,我们可以@customer.name并且假设@customerinstance的{​​{1}},则会收到nil。

我们认为customersingleton class可能对此有所帮助。但我们不太明白他们将如何工作。有人能解释一下这个问题吗?谢谢你的帮助。

3 个答案:

答案 0 :(得分:3)

忽略这一切,额外的评论使这一点毫无价值。

不要覆盖实例方法,为什么不只是有一个实例变量,就像方法的开关一样。

class Project < ActiveRecord::Base

  def phone
    if @do_not_call
      nil
    else
      super
    end
  end

  def do_not_call
    @do_not_call = true
  end

  def do_call
    @do_not_call = false
  end

end

你需要像CanCan这样的东西

https://github.com/ryanb/cancan

使用can can可以设置用户的能力,并执行以下操作。

class Project < ActiveRecord::Base

  def phone
    if current_user can? :phone, self
      super
    else
      nil
    end
  end

end

答案 1 :(得分:1)

覆盖对象(实例)方法的一种方法如下:

@project = Project.find(params[:id])
#@project.phone contains the database value

def @project.phone
  ""
end
#@project.phone returns an empty string now

答案 2 :(得分:1)

既然你说你只想在视图中这样做,那么我觉得视图助手值得考虑:

# view.html.haml
= value_for_view(:phone, @project)

# application_helper.rb
def value_for_view(attribute, object)
  if overide_attributes_in_view? && object.respond_to?("#{attribute}_for_view")
    object.send("#{attribute}_for_view")
  else
    object.send(attribute)
  end
end

# application.rb
def overide_attributes_in_view?
  #do your stuff here to determine whether the original values should be shown or the 'overloads'
end

# project.rb
def phone_for_view
  nil # just add methods called "attribute_for_view" for whatever attributes you want to whatever models you want to have the attributes 'overloaded' (it's not really overloading, but it serves the purpose you describe)
end 

或类似地......你可以修补AR :: Base以获得'value_for_view'方法,因此视图看起来更像是这样:

# view.html.haml
= @project.value_for_view(:phone)

# monkey_patch_file.rb
def value_for_view(attribute)
  if respond_to?("#{attribute}_for_view")
    send("#{attribute}_for_view")
  else
    send(attribute)
  end
end

如果您坚持只能调用@project.phone并获取一个或其他值,那么您需要传递@project一个标志,告诉它为您进行计算,因为Rovermicroer的答案显示(但是,正如我评论的那样,我不确定'超级'会起作用,但原则是正确的。)