【问题标题】:Storing booleans in Active Record Store在 Active Record 存储中存储布尔值
【发布时间】:2021-12-10 18:51:44
【问题描述】:

我正在使用标准的 Rails 表单来更新 ActiveRecord::Store

  store :settings, accessors: %i[is_public]

我的表单如下所示:

<%= form.select(:is_public, options_for_select([['True', true], ['False', false]])) %>

当我查看已保存的已转换为字符串的哈希时,有没有办法在此处保留布尔类型?

【问题讨论】:

  • 这不是一个真正的属性(即存储在表中)是否有原因?如果是这样,您可以覆盖访问器Docs
  • 我只是想将我的所有用户设置存储在一个列中,而不是为 30 多个设置参数设置很多列,有没有更好的方法?
  • 不,这很好,现在更容易理解,但在这种情况下,我建议按照文档中所示覆盖访问器。
  • 我创建了一个自定义模块来添加方法来覆盖访问器,正如@engineersmnky 建议的那样(见下文)。

标签: ruby-on-rails


【解决方案1】:

我能够编写一个 CustomStoreAccessor 模块来覆盖这些属性的访问器:

module CustomStoreAccessor
  def boolean_store_accessor(attr_name)
    define_method "#{attr_name}=" do |value|
      super(value=='true')
    end

    define_method attr_name do
       super()=='true'
    end
  end

  def integer_store_accessor(attr_name)
    define_method "#{attr_name}=" do |value|
      super(value.to_i)
    end

    define_method attr_name do
      super().to_i
    end
  end
end

这允许我将这些方法添加到我的模型中:

class Client < ApplicationRecord
  extend CustomStoreAccessor
  store :settings_object, accessors: %i[is_public max_sessions]
  boolean_store_accessor :is_public
  integer_store_accessor :max_sessions

【讨论】:

  • 由于您的方法在逻辑上被命名,我建议将boolean_store_accessor 分别更改为super(value == 'true')super() == 'true',因为如果这真的是一个布尔值,那么我会一直期待一个布尔值。也不需要"#{attr_name}=".to_sym 中的to_sym String 是完全可以接受的
  • 这真的只是在引出“但是为什么?”这个问题。原生 JSON 类型已经存在很多年了,您的驱动程序将在没有任何这些的情况下将布尔值和数字与 JSON 列相互转换。
【解决方案2】:

不要使用store。除了遗留应用程序之外,它根本没有任何位置。

在 varchar/text 列中存储序列化数据是一种完全过时的方法,因为您的数据库几乎可以肯定具有本机 JSON/JSONB 类型 - 实际上可以有效地查询,而序列化数据如果其编组 Ruby 或 YAML 则不可查询或者如果数据恰好存储为 JSON 字符串,则要求您在查询时对数据进行反序列化。

数据库驱动程序也会自动序列化/反序列化列。使用 store 或其表亲 serialize 实际上会“双重转换”它,因此您最终会得到 JSON 字符串而不是实际有意义的类型,例如对象和数组。

如果您想在 JSON 对象中为“属性”创建访问器,请使用 store_accessor

【讨论】:

  • 我希望能够使用 jsonb 列,但我应该说我使用 store 的原因是我试图获取使用密码箱 gem 保存的加密设置对象。到目前为止,我还不能让密码箱和 JSON 一起工作。并且密码箱说该列必须是文本。有没有更好的办法?
  • 这取决于数据库和要求 - 在 Postgres 上,您可以使用 pgcrypto 扩展和 bytea 列在数据库端进行“整列”加密。
猜你喜欢
  • 1970-01-01
  • 2010-10-25
  • 2012-03-10
  • 2012-08-10
  • 2021-12-04
  • 2019-02-10
  • 1970-01-01
  • 2021-01-04
  • 2015-05-08
相关资源
最近更新 更多