【问题标题】:Accessing instance method from class method从类方法访问实例方法
【发布时间】:2015-07-09 00:40:06
【问题描述】:

我有一个 rails 4 应用程序,它有一个警报模型和与每个警报关联的测试。

创建新警报时,我有一个 after_create 过滤器,它使用实例方法创建新测试:

class Alert < ActiveRecord::Base
    has_many :tests
    after_create :create_test

    private

    def create_test

    #bunch of code using external api to get some data  


     Test.create 

    end
end

我还有一个 cron 作业,我想用它来为每个警报创建一个新测试。我的计划是有一个类方法来做到这一点:

def self.scheduled_test_creation
        @alerts = Alert.all
        @alerts.each do |a|
          a.create_test        
        end
    end

这行不通,因为实例方法是私有的。我知道我可以使用 send 来解决这个问题。或者我可以公开这些方法。或者我可以在实例方法中重写那一堆api代码。

我只是不确定最好的方法是什么。我不想两次编写相同的代码,我想确保是好的做法。也许在这种情况下,方法不必是私有的 - 我知道公共/私有/受保护之间的区别,但我真的不明白什么时候方法应该是私有/受保护的。

任何帮助将不胜感激

【问题讨论】:

  • 当另一个类需要一个方法时,它显然不应该是私有的。或者它在错误的类中。
  • 它们都是 Alert 类的一部分。我不确定这是否应该是这样。我使用任何时候来安排一个调用 Alert.scheduled_test_creation 的 cron 作业
  • 看来你的Alert 班级做得太多了。我很确定 create_test 方法作为 TestBuilder 类会更好看。
  • 这个问题在我看来是“我不小心并且很可能错误地将方法访问级别设置为私有。现在我不能从外面调用它。帮助!” :)
  • @SergioTulentsev 实际上这很有意义。那堂课会去哪里?

标签: ruby-on-rails ruby


【解决方案1】:

我喜欢用于多个模型之间交互的服务类。回调可以使逻辑很难遵循。

例如:

class AlertCreator
  def initialize(alert)
    @alert = alert
  end

  def call
    if @alert.save
      alert_test = TestBuilder.new(@alert).call
      alert_test.save
      true
    end
  end
end

class TestBuilder
  def initialize(alert)
    @alert = alert
  end

  def call
    # external API interaction stuff
    # return unsaved test
  end
end

在您的控制器中,您可以调用AlertCreator.new(@alert).call 而不是通常的@alert.save

【讨论】:

    【解决方案2】:

    我同意@SergioTulentsev 的观点:虽然从长远来看,将这个逻辑分解成一个服务类可能会更好地为您服务,但从短期来看,您只是不应该将方法设为私有,如果它需要在实例之外调用。

    在某些情况下,您实际上想要访问私有方法,例如在测试期间验证对象状态时。这很容易做到:

    @alert.instance_eval{ create_test }
    

    您甚至可以通过这种方式获取或更改实例变量:

    @alert.instance_eval{ @has_code_smells = true }
    

    一般来说,如果您觉得有必要这样做,那么您的逻辑需要重新调整是一种警告气味。忽略这种气味,正是将 Ruby 从一门美妙的语言变成了一种过于强大的语言,让你可以自取其辱。但这是可行的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-12
      • 2021-06-03
      • 2014-01-26
      • 1970-01-01
      • 2013-09-08
      • 2018-11-03
      • 2016-05-20
      • 1970-01-01
      相关资源
      最近更新 更多