【发布时间】:2018-12-19 23:54:38
【问题描述】:
最近我已经厌倦了在我的 app/models 目录中乱扔无意义的样板模型,例如:
- 加入始终包含一对
belongs_tos 而没有其他内容的模型。 - 仅
include SomeConcern并进行几个宏调用的状态日志模型。 - 同样是修订跟踪模型,只需包含关注点并调用宏。
这些模型仅用于支持 has_many 和 has_many ... through: 关联。
根据需要添加生成这些模型的模型关注点可简化 app/models 目录。所以而不是:
has_many :model_things
has_many :things, through: :model_things
还有一个简单的app/models/model_thing.rb 说:
class ModelThing < ApplicationRecord
belongs_to :model
belongs_to :thing
end
我可以通过has_things 宏关注ThingSupport:
根据类名和
has_things的一些选项创建has_many :model_things关联。创建
has_many :things, through: :model_things关联。-
查找或创建
Model::Thing(请参阅下文了解为什么使用此名称)类,调用如下:ModuleUtil.find_or_create(join_model_name) do Class.new(ApplicationRecord) do # Set the table name, call belongs_to as needed, call concern methods, ... end end其中
ModuleUtil.find_or_create是一个简单的方法,它使用String#constantize查找所需的模块(如果存在)或使用块创建它,如果找不到则使用Object#const_set。
所有模型和关联名称都可以使用调用者的类名和has_things 的一些选项(用于特殊情况)中的常用 Rails 约定来构建。
问题是我在这里玩火吗?这种诡计会有什么问题?
我已经遇到的一个问题是,生成的模型类本身并不存在,因此它们不能直接从 ActiveJob(例如 deliver_later 邮件程序)中引用。例如,如果加载Model 会创建ModelThing 关联模型,那么您不能在邮件参数中引用ModelThing,因为ActiveJob 不会知道您必须在ModelThing 存在之前加载Model 类.但是,这可以通过使用Model::Thing 来解决,这样constantize 将在尝试查找Model::Thing 之前查找Model(并在app/models/model.rb 中找到它)(这将存在,因为constantize 将只有加载了Model,它创建了Model::Thing)。我还缺少其他东西吗?
【问题讨论】:
-
哇,金
ruby和ruby-on-rails会员在问问题???????????? -
has_and_belongs_to_many在这里不起作用有什么原因吗? (我假设有,我只是错过了) -
“生成的模型类本身不存在”您可以使用
initializers中的文件来处理这部分。您是否还考虑过查看has_many关系的扩展选项?似乎你可以使这个逻辑模块化和跨类适用 -
@engineersmnky 或者只使用
Model::Thing以便'Model::Thing'.constantize将'Model'.constantize(从而创建Model::Thing)一路走来。我更喜欢命名空间而不是使用初始化程序使事情变得更加分散。是的,我确实将扩展块与所有这些结合使用,有时我会在模块中捕获扩展块,可以混合到生成的类中。 -
@muistooshort
extend可以将完整的模块作为参数,这就是我建议它的原因
标签: ruby-on-rails ruby metaprogramming