Ruby:如何将模块中的方法包含到 ActiveModel::Serializer 的子类中

Ruby: How do I include methods from a Module into a subclass of ActiveModel::Serializer

我正在尝试将辅助模块中的方法包含到 ActiveModel::Serializer 子类中,但由于某种原因该方法未显示。

这是我的简单辅助模块:

module Helpers
  module Serialisers
    def enforce_zulu_time(attribute)
      define_method(attribute) do
        object.send(attribute).utc.iso8601 unless object.try(attribute).nil?
      end
    end
  end
end

这是我的测试序列化器

class TestSerialiser < ActiveModel::Serializer
  include Helpers::Serialisers
  attributes :updated_at

  enforce_zulu_time :updated_at
end

和我要序列化的简单对象

class TestItem
  include ActiveModel::SerializerSupport
  attr_reader :updated_at
  def initialize
    @updated_at = Time.now.utc
  end
end

和我的测试

describe Helpers::Serialisers do
  let(:item)       { TestItem.new }
  let(:serialiser) { TestSerialiser.new(item) }
  subject          { serialiser.attributes }

  it { expect(subject[:updated_at]).to be_zulu_time}
end

结果

`<class:TestSerialiser>': undefined method `enforce_zulu_time' for TestSerialiser:Class (NoMethodError)

但是,如果我只是在 TestSerialiser 中执行此操作,而不是

class TestSerialiser < ActiveModel::Serializer
  attributes :updated_at

  ['updated_at'].each do |attribute|
    define_method(attribute) do
      object.send(attribute).utc.iso8601 unless object.send(attribute).blank?
    end
  end
end

一切正常。

为什么我的 enforce_zulu_time 方法没有被包括在内?

include Helpers::Serialisers 替换为 extend Helpers::Serialisers,因为您需要 class 方法。

另一种解决方案是使用 ActiveSupport::Concernsee doc


旁注

为了让您的代码免费灵活,我建议您为序列化程序创建自己的基础 class,例如:

class BaseSerializer < ActiveModel::Serializer
end

然后让你所有的序列化器继承它。这样您就可以轻松添加功能。