代码之家  ›  专栏  ›  技术社区  ›  0lli.rocks

Ruby/Rails类变量何时初始化?

  •  1
  • 0lli.rocks  · 技术社区  · 7 年前

    我目前面临的问题是,我的所有对象都使用具有“相同”初始值的实例变量,而我只读取了这一个。

    def initialize
        @available_ids = read_only_value
    end
    

    但我不想通过每次创建对象时检索值来实现API。如果改用类变量呢?

    class Foo
       @@available_ids = read_only_value
       def initialize
          @available_ids = @@available_ids //weird but let's go with it
       end
    end
    

    我认为这将解决滥发API的问题,因为它只在变量初始化后执行。。。

    什么时候 这会发生吗?当我启动Rails应用程序时,当我创建第一个对象时?它会被更新吗?由于值每月更改一次,我如何获得更新?

    4 回复  |  直到 7 年前
        1
  •  3
  •   Aleksei Matiushkin    7 年前

    此外,您不需要类变量。类实例变量足够好:

    class Foo
       @available_ids = read_only_value
       def initialize
          @available_ids = self.class.instance_variable_get :@available_ids
       end
    end
    
        2
  •  2
  •   Stefan    7 年前

    Rails具有内置的 cache ,因此沿着这些思路应该可以做到:(基于文档中的示例)

    class Foo
      def available_ids
        Rails.cache.fetch('available_ids', expires_in: 24.hours) do
          API.fetch_ids
        end
      end
    end
    
        3
  •  0
  •   ugandharc18    7 年前

        4
  •  0
  •   eiko    7 年前

    在你的代码中,API将在类被定义时被访问,这意味着当你启动应用程序时,它只能被访问一次。通过这个例子,您可以清楚地看到这一点:

    puts "starting app"
    
    def read_only_value
      puts "API accessed!"
      "my value"
    end
    
    
    class Foo
      @@available_ids = read_only_value
      def initialize
        @available_ids = @@available_ids
        puts "initializing with value: #{@available_ids}"
      end
    end
    
    puts "initializing two objects: "
    Foo.new
    Foo.new
    
    #=> starting app
    #=> API accessed!
    #=> initializing two objects: 
    #=> initializing with value: my value
    #=> initializing with value: my value
    

    当试图管理API访问时,最佳做法是将API封装在自己的类中。这样做可以独立于使用API的对象跟踪API调用和缓存值:

    class API
    
      def self.instance
        @@instance ||= API.new
      end
    
      def read_only_value
        if @read_only_value.nil? || (Time.now - @cached_time) > 86400 # one day, in seconds
          puts "accessing api"
          @read_only_value = "access api here"
          @cached_time = Time.now
        end
        @read_only_value
      end
    
    end
    
    
    class Foo
    
      def initialize
        @available_ids = API.instance.read_only_value
        puts "initializing with value: #{@available_ids}"
      end
    
    end
    
    puts "initializing two objects: "
    
    Foo.new
    Foo.new
    
    #=> initializing two objects: 
    #=> accessing api
    #=> initializing with value: access api here
    #=> initializing with value: access api here