0

在我们的 rails 3.2.12 应用程序中,我们想要override methodfor aninstance并使其返回为空。generic overriding method理想情况下,我们可以为应用程序中的每一个都定义一个model

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

我们在这里感到singleton class并且define_method可能会有所帮助。但我们不太了解它们将如何工作。有人可以阐明这个问题吗?谢谢您的帮助。

4

3 回答 3

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
于 2013-03-31T22:14:22.563 回答
1

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

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

def @project.phone
  ""
end
#@project.phone returns an empty string now
于 2013-03-31T22:49:14.380 回答
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 的回答所示(不过,正如我评论的那样,我不确定'super'会起作用,但原理是正确的)。

于 2013-04-01T08:50:01.190 回答