首页 > 解决方案 > 创建自包含类

问题描述

我的应用程序中有一个特殊模型,它不需要在创建或更新时发送哈希,因此我想创建一个抽象模型,该模型将覆盖 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

我已经在整个网络上搜索了这个,但没有找到任何可以帮助我的东西。

标签: ruby-on-railsactiverecord

解决方案


我会说整个想法是误导。如果您想创建一个仅通过 API 调用而不是用户输入创建的资源,则不要使用路由公开它。

拥有与路由/控制器不对应的模型是完全正常的,如果您担心有人可能能够创建/更新其中一个记录,您应该真正投资于涵盖该记录的测试,而不是更改整个界面活动记录。

通过使其“自包含”来对类本身进行的更改实际上也不是积极的,因为您正在破坏线性流。

@thing = Thing.create(foo: 'bar')
assert_equals('bar', @thing.foo)

这很容易遵循和测试。

现在,如果我们将 Thing 更改为您的 SelfContained 类的实例,则结果实际上取决于内部方法返回的内容。在可读性和可测试性方面,这实际上是一个巨大的倒退。

更不用说两者attributeattributes都是 ActiveModel 和 ActiveRecord 保留的方法名称。

正如@jvillian 提到的那样,从外部源进行 HTTP 调用或任何其他类型的“导入”只会使您的模型进一步膨胀。您很可能希望将客户端类(执行 HTTP 调用)与服务对象(调用客户端并将结果转换为模型)相结合。


推荐阅读