Rails 5 Active Record - 是否可以将表保留在内存中?

时间:2016-09-16 20:55:25

标签: ruby-on-rails ruby caching activerecord in-memory-tables

如果我们有一个包含相对静态数据的小表,是否可以在启动应用程序时将Active Record加载到这个数据中,并且永远不必在数据库中找到这些数据?

请注意,理想情况下,我希望此数据可以与其他与之关系的模型联接。

示例可能是具有电话号码前缀的国家/地区列表 - 此列表不太可能更改,如果确实如此,则会由管理员更改。其他表可能与此有关系(例如,如果有一个引用该国家/地区的用户,我们可能希望查找国家电话前缀)。

我看到了一个类似的问题here,但它已经有6年了,并且引用了Rails 2,而我正在使用Rails 5,从那以后可能会引入一些东西。

首选解决方案是:

  1. 内置Rails / ActiveRecord功能,可以在启动时加载一次表,如果随后加载了与缓存表有关系的其他记录,则自动链接到缓存对象(即手动缓存某个地方的MyModel.all)还不够,因为查询数据库仍会加载关系。)
  2. 维护上述的库。
  3. 如果两者都不可用,我想另一种方法是将静态数据集定义为内存中的枚举/哈希或类似方法,并将哈希键保留在与此数据有关系的记录上,并定义方法使用数据库中持久存储的密钥使用哈希中的对象进行查找的模型。这看起来很简单......
  4. [编辑] 另一个需要考虑的潜在解决方案 - 手动解决方案(3)还需要自定义控制器和路由,以便通过API访问此类数据。理想情况下,如果需要使用标准轨道机制(如脚手架)而不需要太多人工干预,那么可以通过RESTful API(只读 - 只需GET)提供这样的数据提供解决方案。

1 个答案:

答案 0 :(得分:1)

我认为你可能正在打折" easy" /"手册"接近太快了。

将数据写入ruby散列/数组并不是一个好主意。

如果您想使用CRUD脚手架,为什么不使用标准的Rails模型/控制器生成器呢?将一些静态数据存储在数据库中真的很糟糕吗?

第三种选择是将数据以某种序列化格式存储到文件中,然后当您的应用程序加载时读取它并构造ActiveRecord对象。让我举个例子:

data.yml

---
- a: "1"
  b: "1"
- a: "2"
  b: "2"

这是一个包含哈希数组的YAML文件;你可以用:

构建这样一个文件
require 'yaml'
File.open("path.yml", "w") do |f|
  data = [
    { "a" => "1", "b" => 1 },
    { "a" => "2", "b" => 2 }
  ]
  f.write(YAML.dump(data))
end

然后要加载数据,您可以在config/initializers/中创建一个文件(这里的所有内容都将由rails自动加载):

配置/初始化/ static_data.rb

require 'yaml'

# define a constant that can be used by the rest of the app
StaticData = YAML.load(File.read("data.yml")).map do |object|
  MyObjectClass.new(object)
end

为了避免必须为MyObjectClass编写数据库迁移(当它实际上没有存储在数据库中时),您可以对属性使用attr_accessor定义:

class MyObjectClass < ActiveRecord::Base
  # say these are your two columns
  attr_accessor :a, :b
end

确保不要在此模型上运行savedeleteupdate之类的内容(除非您对这些方法进行monkeypatch)。

如果您想拥有REST / CRUD端点,则需要从头开始编写它们,因为现在更改数据的方式不同。 您基本上需要在3个步骤中进行任何更新:

  1. 将数据从YAML加载到Ruby对象列表中
  2. 更改Ruby对象列表
  3. 将所有内容序列化为YAML并保存。
  4. 所以你可以看到你并没有真正在这里进行增量更新。您可以使用JSON而不是YAML,并且您遇到同样的问题。使用Ruby内置的存储系统PStore,您可以单独更新对象,但使用SQL作为生产Web应用程序是一个更好的主意,并且诚实地使事情变得更简单。

    超越这些&#34;序列化数据&#34;选项有key-val存储服务器将数据存储在内存中。像Memcached和Redis这样的东西。

    但回到我之前的观点,除非你有充分的理由不使用SQL,否则你只会让事情变得更加困难。