创建自包含的类

时间:2019-12-11 04:12:57

标签: ruby-on-rails activerecord

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

我已经在网上搜索了所有内容,但找不到任何可以帮助我的东西。

1 个答案:

答案 0 :(得分:1)

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

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

在破坏线性流的过程中,通过使类成为“独立的”而对类本身进行的更改实际上也不是肯定的。

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

这很容易遵循和测试。

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

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

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