首页 > 解决方案 > Ruby on Rails 临时实例变量

问题描述

我想在整个类的方法中使用实例变量。不幸的是,这些方法都是类(不是实例)方法,所以经典方法@my_data ||= [1,2,3]不起作用,因为对类的类方法的每次调用都将永远重用相同的数据:

class MyThing
  class << self

    def do_something
      do_something_else
    end

    private

    def my_data
      @my_data ||= Time.now
    end

    def do_something_else
      puts my_data
    end
  end
end

MyThing.do_something # puts the current time
MyThing.do_something # puts the same time as above (not what I want)

一种解决方法是声明变量,然后在方法的末尾将其设置为 nil,如下所示:

class MyThing
  class << self

    def do_something
      @my_data = my_data
      do_something_else
      @my_data = nil
    end

    private

    def my_data
      Time.now
    end

    def do_something_else
      puts @my_data || my_data
    end
  end
end

MyThing.do_something # puts the current time
MyThing.do_something # puts the new current time (yay)

但是,在方法的开始和结束时设置数据并销毁它似乎很混乱。

有没有更简洁的方式来表示“设置(@my_data = Time.now)直到此方法结束”?

标签: ruby-on-railsruby

解决方案


顾名思义,只要实例存在,所有“实例变量”都可用。在您的情况下,该实例是MyThing类,这意味着它不会自动重置。只要您的程序运行,类就会保持加载状态,因此它永远不会重置。

对于给定场景,最简单的解决方案是使用方法参数。

class MyThing
  class << self
    def do_something
      do_something_else(my_data)
    end

    private

    def do_something_else(my_data)
      puts my_data || Time.now
    end
  end
end

您已经发现的另一个选项,即设置一个实例变量然后重置它。


另一种选择是将您所做的事情转移到一个类实例中。这里的缺点是这种解决方案会产生更多的开销代码。但是,它确实使MyThing类更清洁,因为您可以将辅助方法移动到这个新类中。

class MyThing
  class DataObject
    attr_reader :data

    def initialize(data)
      @data = data || Time.now
    end

    def do_something_else
      puts data
    end
  end

  class << self
    def do_something
      DataObject.new(my_data).do_something_else
    end
  end
end

如果可能的话,你也可以创建一个MyThing实例而不是一个DataObject实例,但我假设这个MyThing类已经有另一个目的。


推荐阅读