如何使实例在 Sinatra 中跨请求持久存在?

How can I make an instance persist across requests in Sinatra?

我正在使用 Sinatra 构建一个非常简单的 'command center' 来控制各种 USB 设备。

我已经像 class Device 一样创建了 类 并对各种类型的设备进行了子分类。

问题是,我不想使用数据库来存储我所有的信息。设备列表永远不会改变,我希望它更便携,只需在常量文件中或简单地定义它们 ruby(我将对设备 ID 等进行硬编码)。

问题是当应用第一次加载时它们出现,当我刷新它们时它们消失了。我试过将它放在应用程序的各个部分,但我不知道它们应该放在哪里。

我也试过将它放在前置过滤器中,但随后它会为每次刷新创建它们的副本(......奇怪的是,当你在第 6 次左右刷新后它会将它们重置回 1,我不知道那是什么。

此外,根据我使用的是 rackup config.ru 还是 thin -R config.ru start,它的行为也大不相同...

谢谢!

app.rb

require 'sinatra'

module RhubarbPi 
  class App < Sinatra::Application
    configure do
      set     :root, App.root
      disable :method_override
    end

    helpers do
      include Rack::Utils
      alias_method :h, :escape_html
    end
  end
end

Dir.glob('./{models,lib,routes}/*.rb').each { |file| require file }

lib/devices.rb(这些是设备本身的实例,我基本上是 'hardcoding')。

USBSK.new(1)
USBSM.new(1)
USBWK.new(1, '192.168.1.127')

这是一个示例模型...简单

class USBSK

  attr_reader :id

  def initialize(id)
    @id = id
  end

  def self.all
    ObjectSpace.each_object(self).to_a
  end

end

在我看来我在做

<% USBSK.all.each do |dev| %>                 
  <ul>                                      
    <li><span>ID:</span> <%= dev.id %></li> 
  </ul>                                     
<% end %>  

您没有保留对对象的任何引用,因此 Ruby 正在对它们进行垃圾回收。另外,不要使用 ObjectSpace 来查找您的项目,它主要用于调试和自省任务。

我会改变 lib/devices.rb 以使用 Ruby 常数,像这样

   class USBSK
     ALL_DEVICES = [
       self.new(1),
       self.new(1),
       self.new(1, '192.168.1.127')
     ]
   end

显然,在定义构造函数后,您将需要 require

然后更改您的 class 全设备访问器:

  def self.all
    ALL_DEVICES
  end