我的应用程序中有一个特殊的模型,该模型不需要在创建或更新时发送哈希,因此我想创建一个抽象模型,该模型将覆盖ApplicationRecord的必要方法,而不需要任何哈希在更新或创建时被传递。到目前为止,我已经提出了这个建议:
class SelfContained < ApplicationRecord
self.abstract_class = true
def create
object = new(attributes)
object.save
object
end
def create!
object = new(attributes)
object.save
object
end
def update
with_transaction_returning_status do
assign_attributes(attributes)
save
end
end
def update!
with_transaction_returning_status do
assign_attributes(attributes)
save!
end
end
end
然后要实现此目的的模型可以:
class ModelName < SelfContained
private
def attribute
get_data_from_outside
end
end
问题是它部分起作用。以下情况不起作用:
ModelName.create # create directly. This should work with ModelName.create(*association_ids)
ModelName.update # update directly. This should work with ModelName.update(id)
parent = ParentModel.find 1; parent.create_model_name
我已经在网上搜索了所有内容,但找不到任何可以帮助我的东西。
答案 0 :(得分:1)
我会说整个想法是误导的。如果要创建仅通过API调用之类的内容创建的资源,而不是用户输入的资源,则不要使用路由公开该资源。
拥有与路由/控制器不对应的模型是完全正常的,如果您担心有人可能会创建/更新这些记录之一,那么您应该真正投资于涵盖该记录的测试,而不是更改ActiveRecord的整个界面。
在破坏线性流的过程中,通过使类成为“独立的”而对类本身进行的更改实际上也不是肯定的。
@thing = Thing.create(foo: 'bar')
assert_equals('bar', @thing.foo)
这很容易遵循和测试。
现在,如果我们将Thing更改为SelfContained类的实例,则结果实际上取决于内部方法返回的内容。在可读性和可测试性方面,这实际上是一个巨大的倒退。
更不用说attribute
和attributes
都是ActiveModel和ActiveRecord保留的方法名称。
就像@jvillian提到的那样,从外部源进行HTTP调用或任何其他类型的“导入”都会使您的模型进一步膨胀。您很可能希望将客户端类(执行HTTP调用)与服务对象(调用客户端并将结果转换为模型)组合在一起。