# ActiveModelSerializers::Model is a convenient
# serializable class to inherit from when making
# serializable non-activerecord objects.
module ActiveModelSerializers
class Model
include ActiveModel::Serializers::JSON
include ActiveModel::Model
class_attribute :attribute_names
# Initialize +attribute_names+ for all subclasses. The array is usually
# mutated in the +attributes+ method, but can be set directly, as well.
self.attribute_names = []
def self.attributes(*names)
self.attribute_names |= names.map(&:to_sym)
# Silence redefinition of methods warnings
ActiveModelSerializers.silence_warnings do
attr_accessor(*names)
end
end
attr_reader :errors
# NOTE that +updated_at+ isn't included in +attribute_names+,
# which means it won't show up in +attributes+ unless a subclass has
# either attributes :updated_at which will redefine the methods
# or attribute_names << :updated_at.
attr_writer :updated_at
# NOTE that +id+ will always be in +attributes+.
attributes :id
def initialize(attributes = {})
@errors = ActiveModel::Errors.new(self)
super
end
# The the fields in +attribute_names+ determines the returned hash.
# +attributes+ are returned frozen to prevent any expectations that mutation affects
# the actual values in the model.
def attributes
attribute_names.each_with_object({}) do |attribute_name, result|
result[attribute_name] = public_send(attribute_name).freeze
end.with_indifferent_access.freeze
end
# To customize model behavior, this method must be redefined. However,
# there are other ways of setting the +cache_key+ a serializer uses.
def cache_key
ActiveSupport::Cache.expand_cache_key([
self.class.model_name.name.downcase,
"#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}"
].compact)
end
# When no set, defaults to the time the file was modified.
# See NOTE by attr_writer :updated_at
def updated_at
defined?(@updated_at) ? @updated_at : File.mtime(__FILE__)
end
# The following methods are needed to be minimally implemented for ActiveModel::Errors
# :nocov:
def self.human_attribute_name(attr, _options = {})
attr
end
def self.lookup_ancestors
[self]
end
# :nocov:
end
end