使用 Module#prepend 查询 str_enum

Using Module#prepend to interrogate a str_enum

我有一个 Rails 模型,它使用 str_enum gem.

我正在构建一个生成器来读取模型并为它们创建页面,因此我希望能够理解 str_enum 附加到模型的内容。

例如

class User < ApplicationRecord
  str_enum :email_frequency, %i[every daily weekly], default: 'every'
end

理想情况下,我希望能够查询 User 模型并了解有一个 str_enum 附加到 email_frequency,其值为 everydaily & weekly.

一旦我理解了给定字段附加了一个 str_enum,我就可以将该字段复数化并获取值:

irb(main):004:0> User.email_frequencies
=> ["every", "daily", "weekly"]

问题也有人问过over here,建议使用Module#prepend。我熟悉 prepend 有条件地将方法插入模型。

如何使用它来解决这个问题?

编辑

这对于验证来说非常简单,例如:get validations from model

如果我对你的问题的理解正确的话,你想获得所有附加了枚举字符串的列。如果是这样,您可以像这样覆盖 gem 方法

# lib/extenstions/str_enum.rb

module Extensions
  module StrEnum
    module ClassMethods
      def str_enum(column, *args)
        self.str_enums << column.to_s.pluralize
        super
      end
    end

    def self.prepended(base)
      class << base
        mattr_accessor :str_enums
        self.str_enums = []
        prepend ClassMethods
      end
    end
  end
end

在用户模型中

prepend Extensions::StrEnum

现在您可以使用

User.str_enums

列出所有列已附加 str 枚举。

确保您已将 lib 目录添加到加载路径中。

因此,对于初学者来说,您当然可以使用 Ninh Le 描述的方法并将您想要的行为猴子修补到 gem 中。事实上,我非常有信心它会起作用,因为您的用例目前相对简单,您实际上只需要跟踪 str_enum 方法被调用的所有时间。

不过,我鼓励您考虑做以下两件事之一:

  • 如果您打算用枚举做更复杂的事情,请考虑使用更重型的枚举 gem 之一,例如 enumerize, enumerate_it or active_enum。所有这些都是已经存在了十年(给予或接受)并且仍然得到支持的软件包,并且所有这些软件包在构建时都考虑到了一定程度的可扩展性和内省(尽管采用了不同的方法)。
  • 看看 gem 并考虑在其上构建您自己的小宏。 IMO Andrew Kane 的图书馆的多个最大弱点之一可以说是他们的那种 hacky/scripty 方法,虽然使图书馆难以扩展,但使它们本质上易于理解,因此可以用作您自己的东西的基础(而具有 better/more 详尽方法的 gem 更难理解和改编,超出了作者的意图)。

无论哪种方式,我的建议和 Ninh Le 的建议都可以。