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

Ruby on rails 如何覆盖rails 3.2.12中实例的方法?,ruby-on-rails,ruby,singleton,Ruby On Rails,Ruby,Singleton,在rails 3.2.12应用程序中,我们希望覆盖实例的方法,并使其返回空。理想情况下,我们可以为应用程序中的每个模型定义一个通用覆盖方法 例如,@project是project模型的实例,phone是列名。方法重写后,我们希望@project.phone在运行时返回空值,而不是列的值。如果应用程序中有另一个型号的客户,我们可以执行@customer.name并接收nil,前提是@customer是客户的实例 我们觉得singleton类和define\u方法在这里可能会有所帮助。但我们不太明白

在rails 3.2.12应用程序中,我们希望
覆盖
实例的
方法,并使其返回空。理想情况下,我们可以为应用程序中的每个
模型定义一个
通用覆盖方法

例如,
@project
project
模型的实例,
phone
是列名。方法重写后,我们希望
@project.phone
在运行时返回空值,而不是列的值。如果应用程序中有另一个型号的
客户
,我们可以执行
@customer.name
并接收nil,前提是
@customer
客户
实例


我们觉得
singleton类
define\u方法
在这里可能会有所帮助。但我们不太明白它们将如何运作。有人能解释一下这个问题吗?谢谢你的帮助。

忽略所有这些,附加的评论使其毫无价值

与其覆盖一个实例方法,不如让一个实例变量充当该方法的开关

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
class项目
你需要像CanCan这样的东西

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

class Project < ActiveRecord::Base

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

end
class项目
忽略所有这些,附加的注释使其毫无价值

与其覆盖一个实例方法,不如让一个实例变量充当该方法的开关

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
class项目
你需要像CanCan这样的东西

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

class Project < ActiveRecord::Base

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

end
class项目
覆盖对象(实例)方法的方法之一是:

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

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

重写对象(实例)的方法的方法之一是:

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

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

既然您说您只想在视图中执行此操作,那么我觉得视图辅助程序值得考虑:

# 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\u for\u 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”是否有效,但原理是正确的)。

因为您说您只想在视图中执行此操作,然后,我想到一个视图辅助程序值得考虑:

# 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\u for\u 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”是否有效,但原理是正确的)。

您是否试图在视图中隐藏电话号码,或者,您是否试图从业务逻辑中隐藏这些实例具有这些特定属性的事实?我不确定实现这一点的最佳方法,但您能否告诉我们为什么需要此功能?例如,它是为了阻止某些用户访问某些列吗?是的,我们将在视图中使用该方法。我们的想法是,不要改变任何事物,而仍然使用,例如,在视图中。当调用@project.phone时,如果用户访问规则这么说,覆盖方法将启动并返回空。这类似于隐藏字段。您是试图在视图中隐藏电话号码,还是试图从业务逻辑中隐藏这些实例具有这些特定属性的事实?我不确定实现这一点的最佳方法,但您能否告诉我们为什么需要此功能?例如,它是为了阻止某些用户访问某些列吗?是的,我们将在视图中使用该方法。我们的想法是,不要改变任何事物,而仍然使用,例如,在视图中。当调用@project.phone时,如果用户访问规则这么说,覆盖方法将启动并返回空。这类似于隐藏字段。该方法将在视图中使用。视图将根据用户访问规则决定列是否为空。这个想法不会改变任何东西。例如,如果用户有权访问phone,则返回phone;如果不基于用户访问规则,则返回空白。然后,您可以执行类似if current_user&¤t_user的操作,而不是if@do_not_call。是否可以看到电话(此),where can_see_phone将是一个针对用户的方法,如果用户可以访问该项目的电话号码,该方法将返回true。因为我们之前不知道哪个字段将为空,除非我们为模型中的每个字段设置定义。有没有一种方法我们只需要定义一次并在所有字段上使用它?我不确定“super”是否会起作用,因为AIUI,属性访问器是由方法提供的。你需要“read_attribute[:phone]”来代替(跑去玩它来检查:-)哦。。您已经在类级别设置了一个实例方法(因此没有任何对象会访问在顶部设置的“@do_not_call”,在调用其中一个do_或do_not_call方法之前,它默认为nil-probs be