最近我已经厌倦了用无意义的样板模型填充app/models
目录,例如:
belongs_to
且没有其他内容的模型。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
我可以对ThingSupport
宏有一个has_things
的关注:
根据类名和has_many :model_things
的一些选项创建has_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
创建(如果找不到)。
所有模型和关联名称都可以使用通常的Rails约定从调用者的类名以及某些特殊情况的has_things
选项中构建。
问题是我在这里玩火吗?这种骗子怎么办?
我已经遇到的一个问题是,生成的模型类本身并不存在,因此无法直接从ActiveJob(例如deliver_later
邮件程序)中引用它们。例如,如果加载Model
创建了ModelThing
关联模型,则您不能在mailer参数中引用ModelThing
,因为ActiveJob不会知道您必须加载{{1 }}在Model
之前的类。但是,这可以通过使用ModelThing
来解决,这样Model::Thing
会在尝试找到constantize
之前先寻找Model
(并在app/models/model.rb
中找到它)(之所以会存在,是因为Model::Thing
刚刚加载了constantize
并创建了Model
)。我还想念其他东西吗?
答案 0 :(得分:3)
我不知道是否关注您。因此,如果这离目标很远,请这样说,我将删除。
关注加入模型位时,我也厌倦了那种火焰。因此,我创建了一个模型,例如:
module ActsAsHaving
class HasA < ActiveRecord::Base
validates :haser_type, :haser_id, :hased_type, :hased_id, presence: true
belongs_to :hased, polymorphic: true
belongs_to :haser, polymorphic: true
acts_as_taggable
def haser=(thing)
self.haser_type = thing.class.name
self.haser_id = thing.id
end
def haser
haser_type.constantize.find_by(id: haser_id)
end
def hased=(thing)
self.hased_type = thing.class.name
self.hased_id = thing.id
end
def hased
hased_type.constantize.find_by(id: hased_id)
end
end
end
我没有使用内置的访问器和验证,因为有时我会使用它来连接非AR记录(我从远程API服务中获取这些记录,其中一些属于我,有些不属于我,但这是一个更长的故事)。
无论如何,然后我写了一个acts_as_having
宏,让我可以做类似的事情:
class Person < ActiveRecord::Base
acts_as_having :health_events, class_name: "Foo::Event", tag_with: "health_event", remote: true
acts_as_having :program_events, class_name: "Foo::Event", tag_with: "program_event", remote: true
acts_as_having :email_addresses, :phone_numbers, :physical_addresses
end
哪个给了我类似的东西
@person.email_addresses
@person.email_addresses << @email_address
etc...
我可以做相反的事情:
class EmailAddress < ActiveRecord::Base
acts_as_had_by :person
end
哪个给了我类似的东西
@email_address.person
etc...
然后,我将所有垃圾包裹成宝石。现在,我很少创建联接模型,除非它们有一些特定的要求,而我无法将自己塞入acts_as_having
位。
无论如何,我不知道它是否在玩火。我什至不知道我是有道理还是在解决您的概念。但是,我大约三年前开始创业,我并不后悔。所以,就是这样。