mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-25 07:16:49 +00:00
Merge 0-10-stable into master (to fix breaking change). (#2023)
* Merge pull request #1990 from mxie/mx-result-typo Fix typos and capitalization in Relationship Links docs [ci skip] * Merge pull request #1992 from ojiry/bump_ruby_versions Run tests by Ruby 2.2.6 and 2.3.3 * Merge pull request #1994 from bf4/promote_architecture Promote important architecture description that answers a lot of questions we get Conflicts: docs/ARCHITECTURE.md * Merge pull request #1999 from bf4/typos Fix typos [ci skip] * Merge pull request #2000 from berfarah/patch-1 Link to 0.10.3 tag instead of `master` branch * Merge pull request #2007 from bf4/check_ci Test was failing due to change in JSON exception message when parsing empty string * Swap out KeyTransform for CaseTransform (#1993) * delete KeyTransform, use CaseTransform * added changelog Conflicts: CHANGELOG.md * Merge pull request #2005 from kofronpi/support-ruby-2.4 Update jsonapi runtime dependency to 0.1.1.beta6 * Bump to v0.10.4 * Merge pull request #2018 from rails-api/bump_version Bump to v0.10.4 [ci skip] Conflicts: CHANGELOG.md * Merge pull request #2019 from bf4/fix_method_redefined_warning Fix AMS warnings * Merge pull request #2020 from bf4/silence_grape_warnings Silence Grape warnings * Merge pull request #2017 from bf4/remove_warnings Fix mt6 assert_nil warnings * Updated isolated tests to assert correct behavior. (#2010) * Updated isolated tests to assert correct behavior. * Added check to get unsafe params if rails version is great than 5 * Merge pull request #2012 from bf4/cleanup_isolated_jsonapi_renderer_tests_a_bit Cleanup assertions in isolated jsonapi renderer tests a bit * Add Model#attributes helper; make test attributes explicit * Fix model attributes accessors * Fix typos * Randomize testing of compatibility layer against regressions * Test bugfix * Add CHANGELOG * Merge pull request #1981 from groyoh/link_doc Fix relationship links doc Conflicts: CHANGELOG.md
This commit is contained in:
committed by
GitHub
parent
2a6d373cb2
commit
93ca27fe44
@@ -1,16 +1,40 @@
|
||||
# ActiveModelSerializers::Model is a convenient
|
||||
# serializable class to inherit from when making
|
||||
# serializable non-activerecord objects.
|
||||
# ActiveModelSerializers::Model is a convenient superclass for making your models
|
||||
# from Plain-Old Ruby Objects (PORO). It also serves as a reference implementation
|
||||
# that satisfies ActiveModel::Serializer::Lint::Tests.
|
||||
module ActiveModelSerializers
|
||||
class Model
|
||||
include ActiveModel::Serializers::JSON
|
||||
include ActiveModel::Model
|
||||
|
||||
class_attribute :attribute_names
|
||||
# Declare names of attributes to be included in +sttributes+ hash.
|
||||
# Is only available as a class-method since the ActiveModel::Serialization mixin in Rails
|
||||
# uses an +attribute_names+ local variable, which may conflict if we were to add instance methods here.
|
||||
#
|
||||
# @overload attribute_names
|
||||
# @return [Array<Symbol>]
|
||||
class_attribute :attribute_names, instance_writer: false, instance_reader: false
|
||||
# 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 = []
|
||||
|
||||
# Easily declare instance attributes with setters and getters for each.
|
||||
#
|
||||
# All attributes to initialize an instance must have setters.
|
||||
# However, the hash turned by +attributes+ instance method will ALWAYS
|
||||
# be the value of the initial attributes, regardless of what accessors are defined.
|
||||
# The only way to change the change the attributes after initialization is
|
||||
# to mutate the +attributes+ directly.
|
||||
# Accessor methods do NOT mutate the attributes. (This is a bug).
|
||||
#
|
||||
# @note For now, the Model only supports the notion of 'attributes'.
|
||||
# In the tests, there is a special Model that also supports 'associations'. This is
|
||||
# important so that we can add accessors for values that should not appear in the
|
||||
# attributes hash when modeling associations. It is not yet clear if it
|
||||
# makes sense for a PORO to have associations outside of the tests.
|
||||
#
|
||||
# @overload attributes(names)
|
||||
# @param names [Array<String, Symbol>]
|
||||
# @param name [String, Symbol]
|
||||
def self.attributes(*names)
|
||||
self.attribute_names |= names.map(&:to_sym)
|
||||
# Silence redefinition of methods warnings
|
||||
@@ -19,31 +43,90 @@ module ActiveModelSerializers
|
||||
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 <tt>attributes :updated_at</tt> which will redefine the methods
|
||||
# or <tt>attribute_names << :updated_at</tt>.
|
||||
attr_writer :updated_at
|
||||
# NOTE that +id+ will always be in +attributes+.
|
||||
attributes :id
|
||||
# Opt-in to breaking change
|
||||
def self.derive_attributes_from_names_and_fix_accessors
|
||||
unless included_modules.include?(DeriveAttributesFromNamesAndFixAccessors)
|
||||
prepend(DeriveAttributesFromNamesAndFixAccessors)
|
||||
end
|
||||
end
|
||||
|
||||
module DeriveAttributesFromNamesAndFixAccessors
|
||||
def self.included(base)
|
||||
# NOTE that +id+ will always be in +attributes+.
|
||||
base.attributes :id
|
||||
end
|
||||
|
||||
# Override the initialize method so that attributes aren't processed.
|
||||
#
|
||||
# @param attributes [Hash]
|
||||
def initialize(attributes = {})
|
||||
@errors = ActiveModel::Errors.new(self)
|
||||
super
|
||||
end
|
||||
|
||||
# Override the +attributes+ method so that the hash is derived from +attribute_names+.
|
||||
#
|
||||
# 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
|
||||
self.class.attribute_names.each_with_object({}) do |attribute_name, result|
|
||||
result[attribute_name] = public_send(attribute_name).freeze
|
||||
end.with_indifferent_access.freeze
|
||||
end
|
||||
end
|
||||
|
||||
# Support for validation and other ActiveModel::Errors
|
||||
# @return [ActiveModel::Errors]
|
||||
attr_reader :errors
|
||||
|
||||
# (see #updated_at)
|
||||
attr_writer :updated_at
|
||||
|
||||
# The only way to change the attributes of an instance is to directly mutate the attributes.
|
||||
# @example
|
||||
#
|
||||
# model.attributes[:foo] = :bar
|
||||
# @return [Hash]
|
||||
attr_reader :attributes
|
||||
|
||||
# @param attributes [Hash]
|
||||
def initialize(attributes = {})
|
||||
attributes ||= {} # protect against nil
|
||||
@attributes = attributes.symbolize_keys.with_indifferent_access
|
||||
@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
|
||||
# Defaults to the downcased model name.
|
||||
# This probably isn't a good default, since it's not a unique instance identifier,
|
||||
# but that's what is currently implemented \_('-')_/.
|
||||
#
|
||||
# @note Though +id+ is defined, it will only show up
|
||||
# in +attributes+ when it is passed in to the initializer or added to +attributes+,
|
||||
# such as <tt>attributes[:id] = 5</tt>.
|
||||
# @return [String, Numeric, Symbol]
|
||||
def id
|
||||
attributes.fetch(:id) do
|
||||
defined?(@id) ? @id : self.class.model_name.name && self.class.model_name.name.downcase
|
||||
end
|
||||
end
|
||||
|
||||
# When not set, defaults to the time the file was modified.
|
||||
#
|
||||
# @note Though +updated_at+ and +updated_at=+ are defined, it will only show up
|
||||
# in +attributes+ when it is passed in to the initializer or added to +attributes+,
|
||||
# such as <tt>attributes[:updated_at] = Time.current</tt>.
|
||||
# @return [String, Numeric, Time]
|
||||
def updated_at
|
||||
attributes.fetch(:updated_at) do
|
||||
defined?(@updated_at) ? @updated_at : File.mtime(__FILE__)
|
||||
end
|
||||
end
|
||||
|
||||
# To customize model behavior, this method must be redefined. However,
|
||||
# there are other ways of setting the +cache_key+ a serializer uses.
|
||||
# @return [String]
|
||||
def cache_key
|
||||
ActiveSupport::Cache.expand_cache_key([
|
||||
self.class.model_name.name.downcase,
|
||||
@@ -51,12 +134,6 @@ module ActiveModelSerializers
|
||||
].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 = {})
|
||||
|
||||
Reference in New Issue
Block a user