tiny-max-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/active_model_serializers-0.10.16/CHANGELOG.md +793 -0
  3. data/active_model_serializers-0.10.16/MIT-LICENSE +22 -0
  4. data/active_model_serializers-0.10.16/README.md +304 -0
  5. data/active_model_serializers-0.10.16/lib/action_controller/serialization.rb +76 -0
  6. data/active_model_serializers-0.10.16/lib/active_model/serializable_resource.rb +13 -0
  7. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter/attributes.rb +17 -0
  8. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter/base.rb +20 -0
  9. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter/json.rb +17 -0
  10. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter/json_api.rb +17 -0
  11. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter/null.rb +17 -0
  12. data/active_model_serializers-0.10.16/lib/active_model/serializer/adapter.rb +26 -0
  13. data/active_model_serializers-0.10.16/lib/active_model/serializer/array_serializer.rb +14 -0
  14. data/active_model_serializers-0.10.16/lib/active_model/serializer/association.rb +73 -0
  15. data/active_model_serializers-0.10.16/lib/active_model/serializer/attribute.rb +27 -0
  16. data/active_model_serializers-0.10.16/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  17. data/active_model_serializers-0.10.16/lib/active_model/serializer/collection_serializer.rb +99 -0
  18. data/active_model_serializers-0.10.16/lib/active_model/serializer/concerns/caching.rb +305 -0
  19. data/active_model_serializers-0.10.16/lib/active_model/serializer/error_serializer.rb +16 -0
  20. data/active_model_serializers-0.10.16/lib/active_model/serializer/errors_serializer.rb +34 -0
  21. data/active_model_serializers-0.10.16/lib/active_model/serializer/field.rb +92 -0
  22. data/active_model_serializers-0.10.16/lib/active_model/serializer/fieldset.rb +33 -0
  23. data/active_model_serializers-0.10.16/lib/active_model/serializer/has_many_reflection.rb +12 -0
  24. data/active_model_serializers-0.10.16/lib/active_model/serializer/has_one_reflection.rb +9 -0
  25. data/active_model_serializers-0.10.16/lib/active_model/serializer/lazy_association.rb +99 -0
  26. data/active_model_serializers-0.10.16/lib/active_model/serializer/link.rb +23 -0
  27. data/active_model_serializers-0.10.16/lib/active_model/serializer/lint.rb +152 -0
  28. data/active_model_serializers-0.10.16/lib/active_model/serializer/null.rb +19 -0
  29. data/active_model_serializers-0.10.16/lib/active_model/serializer/reflection.rb +212 -0
  30. data/active_model_serializers-0.10.16/lib/active_model/serializer/version.rb +7 -0
  31. data/active_model_serializers-0.10.16/lib/active_model/serializer.rb +430 -0
  32. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/attributes.rb +36 -0
  33. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/base.rb +85 -0
  34. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json.rb +23 -0
  35. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  36. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  37. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  38. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  39. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  40. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/pagination_links.rb +94 -0
  41. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  42. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  43. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/json_api.rb +535 -0
  44. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter/null.rb +11 -0
  45. data/active_model_serializers-0.10.16/lib/active_model_serializers/adapter.rb +100 -0
  46. data/active_model_serializers-0.10.16/lib/active_model_serializers/callbacks.rb +57 -0
  47. data/active_model_serializers-0.10.16/lib/active_model_serializers/deprecate.rb +56 -0
  48. data/active_model_serializers-0.10.16/lib/active_model_serializers/deserialization.rb +17 -0
  49. data/active_model_serializers-0.10.16/lib/active_model_serializers/json_pointer.rb +16 -0
  50. data/active_model_serializers-0.10.16/lib/active_model_serializers/logging.rb +124 -0
  51. data/active_model_serializers-0.10.16/lib/active_model_serializers/lookup_chain.rb +82 -0
  52. data/active_model_serializers-0.10.16/lib/active_model_serializers/model.rb +132 -0
  53. data/active_model_serializers-0.10.16/lib/active_model_serializers/railtie.rb +62 -0
  54. data/active_model_serializers-0.10.16/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  55. data/active_model_serializers-0.10.16/lib/active_model_serializers/serializable_resource.rb +84 -0
  56. data/active_model_serializers-0.10.16/lib/active_model_serializers/serialization_context.rb +41 -0
  57. data/active_model_serializers-0.10.16/lib/active_model_serializers/test/schema.rb +140 -0
  58. data/active_model_serializers-0.10.16/lib/active_model_serializers/test/serializer.rb +127 -0
  59. data/active_model_serializers-0.10.16/lib/active_model_serializers/test.rb +9 -0
  60. data/active_model_serializers-0.10.16/lib/active_model_serializers.rb +63 -0
  61. data/active_model_serializers-0.10.16/lib/generators/rails/USAGE +6 -0
  62. data/active_model_serializers-0.10.16/lib/generators/rails/resource_override.rb +12 -0
  63. data/active_model_serializers-0.10.16/lib/generators/rails/serializer_generator.rb +38 -0
  64. data/active_model_serializers-0.10.16/lib/generators/rails/templates/serializer.rb.erb +8 -0
  65. data/active_model_serializers-0.10.16/lib/grape/active_model_serializers.rb +18 -0
  66. data/active_model_serializers-0.10.16/lib/grape/formatters/active_model_serializers.rb +34 -0
  67. data/active_model_serializers-0.10.16/lib/grape/helpers/active_model_serializers.rb +19 -0
  68. data/active_model_serializers-0.10.16/lib/tasks/rubocop.rake +60 -0
  69. data/tiny-max-kit.gemspec +12 -0
  70. metadata +109 -0
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module Adapter
5
+ UnknownAdapterError = Class.new(ArgumentError)
6
+ ADAPTER_MAP = {} # rubocop:disable Style/MutableConstant
7
+ private_constant :ADAPTER_MAP if defined?(private_constant)
8
+
9
+ class << self # All methods are class functions
10
+ # :nocov:
11
+ def new(*args)
12
+ fail ArgumentError, 'Adapters inherit from Adapter::Base.' \
13
+ "Adapter.new called with args: '#{args.inspect}', from" \
14
+ "'caller[0]'."
15
+ end
16
+ # :nocov:
17
+
18
+ def configured_adapter
19
+ lookup(ActiveModelSerializers.config.adapter)
20
+ end
21
+
22
+ def create(resource, options = {})
23
+ override = options.delete(:adapter)
24
+ klass = override ? adapter_class(override) : configured_adapter
25
+ klass.new(resource, options)
26
+ end
27
+
28
+ # @see ActiveModelSerializers::Adapter.lookup
29
+ def adapter_class(adapter)
30
+ ActiveModelSerializers::Adapter.lookup(adapter)
31
+ end
32
+
33
+ # @return [Hash<adapter_name, adapter_class>]
34
+ def adapter_map
35
+ ADAPTER_MAP
36
+ end
37
+
38
+ # @return [Array<Symbol>] list of adapter names
39
+ def adapters
40
+ adapter_map.keys.sort!
41
+ end
42
+
43
+ # Adds an adapter 'klass' with 'name' to the 'adapter_map'
44
+ # Names are stringified and underscored
45
+ # @param name [Symbol, String, Class] name of the registered adapter
46
+ # @param klass [Class] adapter class itself, optional if name is the class
47
+ # @example
48
+ # AMS::Adapter.register(:my_adapter, MyAdapter)
49
+ # @note The registered name strips out 'ActiveModelSerializers::Adapter::'
50
+ # so that registering 'ActiveModelSerializers::Adapter::Json' and
51
+ # 'Json' will both register as 'json'.
52
+ def register(name, klass = name)
53
+ name = name.to_s.gsub(/\AActiveModelSerializers::Adapter::/, ''.freeze)
54
+ adapter_map[name.underscore] = klass
55
+ self
56
+ end
57
+
58
+ def registered_name(adapter_class)
59
+ ADAPTER_MAP.key adapter_class
60
+ end
61
+
62
+ # @param adapter [String, Symbol, Class] name to fetch adapter by
63
+ # @return [ActiveModelSerializers::Adapter] subclass of Adapter
64
+ # @raise [UnknownAdapterError]
65
+ def lookup(adapter)
66
+ # 1. return if is a class
67
+ return adapter if adapter.is_a?(Class)
68
+ adapter_name = adapter.to_s.underscore
69
+ # 2. return if registered
70
+ adapter_map.fetch(adapter_name) do
71
+ # 3. try to find adapter class from environment
72
+ adapter_class = find_by_name(adapter_name)
73
+ register(adapter_name, adapter_class)
74
+ adapter_class
75
+ end
76
+ rescue NameError, ArgumentError => e
77
+ failure_message =
78
+ "NameError: #{e.message}. Unknown adapter: #{adapter.inspect}. Valid adapters are: #{adapters}"
79
+ raise UnknownAdapterError, failure_message, e.backtrace
80
+ end
81
+
82
+ # @api private
83
+ def find_by_name(adapter_name)
84
+ adapter_name = adapter_name.to_s.classify.tr('API', 'Api')
85
+ "ActiveModelSerializers::Adapter::#{adapter_name}".safe_constantize ||
86
+ "ActiveModelSerializers::Adapter::#{adapter_name.pluralize}".safe_constantize or # rubocop:disable Style/AndOr
87
+ fail UnknownAdapterError
88
+ end
89
+ private :find_by_name
90
+ end
91
+
92
+ # Gotta be at the bottom to use the code above it :(
93
+ extend ActiveSupport::Autoload
94
+ autoload :Base
95
+ autoload :Null
96
+ autoload :Attributes
97
+ autoload :Json
98
+ autoload :JsonApi
99
+ end
100
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adapted from
4
+ # https://github.com/rails/rails/blob/7f18ea14c8/activejob/lib/active_job/callbacks.rb
5
+ require 'active_support/callbacks'
6
+
7
+ module ActiveModelSerializers
8
+ # = ActiveModelSerializers Callbacks
9
+ #
10
+ # ActiveModelSerializers provides hooks during the life cycle of serialization and
11
+ # allow you to trigger logic. Available callbacks are:
12
+ #
13
+ # * <tt>around_render</tt>
14
+ #
15
+ module Callbacks
16
+ extend ActiveSupport::Concern
17
+ include ActiveSupport::Callbacks
18
+
19
+ included do
20
+ define_callbacks :render
21
+ end
22
+
23
+ # These methods will be included into any ActiveModelSerializers object, adding
24
+ # callbacks for +render+.
25
+ module ClassMethods
26
+ # Defines a callback that will get called around the render method,
27
+ # whether it is as_json, to_json, or serializable_hash
28
+ #
29
+ # class ActiveModelSerializers::SerializableResource
30
+ # include ActiveModelSerializers::Callbacks
31
+ #
32
+ # around_render do |args, block|
33
+ # tag_logger do
34
+ # notify_render do
35
+ # block.call(args)
36
+ # end
37
+ # end
38
+ # end
39
+ #
40
+ # def as_json
41
+ # run_callbacks :render do
42
+ # adapter.as_json
43
+ # end
44
+ # end
45
+ # # Note: So that we can re-use the instrumenter for as_json, to_json, and
46
+ # # serializable_hash, we aren't using the usual format, which would be:
47
+ # # def render(args)
48
+ # # adapter.as_json
49
+ # # end
50
+ # end
51
+ #
52
+ def around_render(*filters, &blk)
53
+ set_callback(:render, :around, *filters, &blk)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Provides a single method +deprecate+ to be used to declare when
5
+ # something is going away.
6
+ #
7
+ # class Legacy
8
+ # def self.klass_method
9
+ # # ...
10
+ # end
11
+ #
12
+ # def instance_method
13
+ # # ...
14
+ # end
15
+ #
16
+ # extend ActiveModelSerializers::Deprecate
17
+ # deprecate :instance_method, "ActiveModelSerializers::NewPlace#new_method"
18
+ #
19
+ # class << self
20
+ # extend ActiveModelSerializers::Deprecate
21
+ # deprecate :klass_method, :none
22
+ # end
23
+ # end
24
+ #
25
+ # Adapted from https://github.com/rubygems/rubygems/blob/1591331/lib/rubygems/deprecate.rb
26
+ module ActiveModelSerializers
27
+ module Deprecate
28
+ ##
29
+ # Simple deprecation method that deprecates +name+ by wrapping it up
30
+ # in a dummy method. It warns on each call to the dummy method
31
+ # telling the user of +replacement+ (unless +replacement+ is :none) that it is planned to go away.
32
+
33
+ def deprecate(name, replacement)
34
+ old = "_deprecated_#{name}"
35
+ alias_method old, name
36
+ class_eval do
37
+ define_method(name) do |*args, &block|
38
+ target = is_a?(Module) ? "#{self}." : "#{self.class}#"
39
+ msg = ["NOTE: #{target}#{name} is deprecated",
40
+ replacement == :none ? ' with no replacement' : "; use #{replacement} instead",
41
+ "\n#{target}#{name} called from #{ActiveModelSerializers.location_of_caller.join(':')}"]
42
+ warn "#{msg.join}."
43
+ send old, *args, &block
44
+ end
45
+ end
46
+ end
47
+
48
+ def delegate_and_deprecate(method, delegee)
49
+ delegate method, to: delegee
50
+ deprecate method, "#{delegee.name}."
51
+ end
52
+
53
+ module_function :deprecate
54
+ module_function :delegate_and_deprecate
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module Deserialization
5
+ module_function
6
+
7
+ def jsonapi_parse(*args)
8
+ Adapter::JsonApi::Deserialization.parse(*args)
9
+ end
10
+
11
+ # :nocov:
12
+ def jsonapi_parse!(*args)
13
+ Adapter::JsonApi::Deserialization.parse!(*args)
14
+ end
15
+ # :nocov:
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module JsonPointer
5
+ module_function
6
+
7
+ POINTERS = {
8
+ attribute: '/data/attributes/%s'.freeze,
9
+ primary_data: '/data%s'.freeze
10
+ }.freeze
11
+
12
+ def new(pointer_type, value = nil)
13
+ format(POINTERS[pointer_type], value)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # ActiveModelSerializers::Logging
5
+ #
6
+ # https://github.com/rails/rails/blob/280654ef88/activejob/lib/active_job/logging.rb
7
+ #
8
+ module ActiveModelSerializers
9
+ module Logging
10
+ RENDER_EVENT = 'render.active_model_serializers'.freeze
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ include ActiveModelSerializers::Callbacks
15
+ extend Macros
16
+ instrument_rendering
17
+ end
18
+
19
+ module ClassMethods
20
+ def instrument_rendering
21
+ around_render do |args, block|
22
+ tag_logger do
23
+ notify_render do
24
+ block.call(args)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # Macros that can be used to customize the logging of class or instance methods,
32
+ # by extending the class or its singleton.
33
+ #
34
+ # Adapted from:
35
+ # https://github.com/rubygems/rubygems/blob/cb28f5e991/lib/rubygems/deprecate.rb
36
+ #
37
+ # Provides a single method +notify+ to be used to declare when
38
+ # something a method notifies, with the argument +callback_name+ of the notification callback.
39
+ #
40
+ # class Adapter
41
+ # def self.klass_method
42
+ # # ...
43
+ # end
44
+ #
45
+ # def instance_method
46
+ # # ...
47
+ # end
48
+ #
49
+ # include ActiveModelSerializers::Logging::Macros
50
+ # notify :instance_method, :render
51
+ #
52
+ # class << self
53
+ # extend ActiveModelSerializers::Logging::Macros
54
+ # notify :klass_method, :render
55
+ # end
56
+ # end
57
+ module Macros
58
+ ##
59
+ # Simple notify method that wraps up +name+
60
+ # in a dummy method. It notifies on with the +callback_name+ notifier on
61
+ # each call to the dummy method, telling what the current serializer and adapter
62
+ # are being rendered.
63
+ # Adapted from:
64
+ # https://github.com/rubygems/rubygems/blob/cb28f5e991/lib/rubygems/deprecate.rb
65
+ def notify(name, callback_name)
66
+ class_eval do
67
+ old = "_notifying_#{callback_name}_#{name}"
68
+ alias_method old, name
69
+ define_method name do |*args, &block|
70
+ run_callbacks callback_name do
71
+ send old, *args, &block
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def notify_render(*)
79
+ event_name = RENDER_EVENT
80
+ ActiveSupport::Notifications.instrument(event_name, notify_render_payload) do
81
+ yield
82
+ end
83
+ end
84
+
85
+ def notify_render_payload
86
+ {
87
+ serializer: serializer || ActiveModel::Serializer::Null,
88
+ adapter: adapter || ActiveModelSerializers::Adapter::Null
89
+ }
90
+ end
91
+
92
+ private
93
+
94
+ def tag_logger(*tags)
95
+ if ActiveModelSerializers.logger.respond_to?(:tagged)
96
+ tags.unshift 'active_model_serializers'.freeze unless logger_tagged_by_active_model_serializers?
97
+ ActiveModelSerializers.logger.tagged(*tags) { yield }
98
+ else
99
+ yield
100
+ end
101
+ end
102
+
103
+ def logger_tagged_by_active_model_serializers?
104
+ ActiveModelSerializers.logger.formatter.current_tags.include?('active_model_serializers'.freeze)
105
+ end
106
+
107
+ class LogSubscriber < ActiveSupport::LogSubscriber
108
+ def render(event)
109
+ info do
110
+ serializer = event.payload[:serializer]
111
+ adapter = event.payload[:adapter]
112
+ duration = event.duration.round(2)
113
+ "Rendered #{serializer.name} with #{adapter.class} (#{duration}ms)"
114
+ end
115
+ end
116
+
117
+ def logger
118
+ ActiveModelSerializers.logger
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ ActiveModelSerializers::Logging::LogSubscriber.attach_to :active_model_serializers
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module LookupChain
5
+ # Standard appending of Serializer to the resource name.
6
+ #
7
+ # Example:
8
+ # Author => AuthorSerializer
9
+ BY_RESOURCE = lambda do |resource_class, _serializer_class, _namespace|
10
+ serializer_from(resource_class)
11
+ end
12
+
13
+ # Uses the namespace of the resource to find the serializer
14
+ #
15
+ # Example:
16
+ # British::Author => British::AuthorSerializer
17
+ BY_RESOURCE_NAMESPACE = lambda do |resource_class, _serializer_class, _namespace|
18
+ resource_namespace = namespace_for(resource_class)
19
+ serializer_name = serializer_from(resource_class)
20
+
21
+ "#{resource_namespace}::#{serializer_name}"
22
+ end
23
+
24
+ # Uses the controller namespace of the resource to find the serializer
25
+ #
26
+ # Example:
27
+ # Api::V3::AuthorsController => Api::V3::AuthorSerializer
28
+ BY_NAMESPACE = lambda do |resource_class, _serializer_class, namespace|
29
+ resource_name = resource_class_name(resource_class)
30
+ namespace ? "#{namespace}::#{resource_name}Serializer" : nil
31
+ end
32
+
33
+ # Allows for serializers to be defined in parent serializers
34
+ # - useful if a relationship only needs a different set of attributes
35
+ # than if it were rendered independently.
36
+ #
37
+ # Example:
38
+ # class BlogSerializer < ActiveModel::Serializer
39
+ # class AuthorSerialier < ActiveModel::Serializer
40
+ # ...
41
+ # end
42
+ #
43
+ # belongs_to :author
44
+ # ...
45
+ # end
46
+ #
47
+ # The belongs_to relationship would be rendered with
48
+ # BlogSerializer::AuthorSerialier
49
+ BY_PARENT_SERIALIZER = lambda do |resource_class, serializer_class, _namespace|
50
+ return if serializer_class == ActiveModel::Serializer
51
+
52
+ serializer_name = serializer_from(resource_class)
53
+ "#{serializer_class}::#{serializer_name}"
54
+ end
55
+
56
+ DEFAULT = [
57
+ BY_PARENT_SERIALIZER,
58
+ BY_NAMESPACE,
59
+ BY_RESOURCE_NAMESPACE,
60
+ BY_RESOURCE
61
+ ].freeze
62
+
63
+ module_function
64
+
65
+ def namespace_for(klass)
66
+ klass.name.deconstantize
67
+ end
68
+
69
+ def resource_class_name(klass)
70
+ klass.name.demodulize
71
+ end
72
+
73
+ def serializer_from_resource_name(name)
74
+ "#{name}Serializer"
75
+ end
76
+
77
+ def serializer_from(klass)
78
+ name = resource_class_name(klass)
79
+ serializer_from_resource_name(name)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ActiveModelSerializers::Model is a convenient superclass for making your models
4
+ # from Plain-Old Ruby Objects (PORO). It also serves as a reference implementation
5
+ # that satisfies ActiveModel::Serializer::Lint::Tests.
6
+ require 'active_support/core_ext/hash'
7
+ module ActiveModelSerializers
8
+ class Model
9
+ include ActiveModel::Serializers::JSON
10
+ include ActiveModel::Model
11
+
12
+ # Declare names of attributes to be included in +attributes+ hash.
13
+ # Is only available as a class-method since the ActiveModel::Serialization mixin in Rails
14
+ # uses an +attribute_names+ local variable, which may conflict if we were to add instance methods here.
15
+ #
16
+ # @overload attribute_names
17
+ # @return [Array<Symbol>]
18
+ class_attribute :attribute_names, instance_writer: false, instance_reader: false
19
+ # Initialize +attribute_names+ for all subclasses. The array is usually
20
+ # mutated in the +attributes+ method, but can be set directly, as well.
21
+ self.attribute_names = []
22
+
23
+ # Easily declare instance attributes with setters and getters for each.
24
+ #
25
+ # To initialize an instance, all attributes must have setters.
26
+ # However, the hash returned by +attributes+ instance method will ALWAYS
27
+ # be the value of the initial attributes, regardless of what accessors are defined.
28
+ # The only way to change the change the attributes after initialization is
29
+ # to mutate the +attributes+ directly.
30
+ # Accessor methods do NOT mutate the attributes. (This is a bug).
31
+ #
32
+ # @note For now, the Model only supports the notion of 'attributes'.
33
+ # In the tests, there is a special Model that also supports 'associations'. This is
34
+ # important so that we can add accessors for values that should not appear in the
35
+ # attributes hash when modeling associations. It is not yet clear if it
36
+ # makes sense for a PORO to have associations outside of the tests.
37
+ #
38
+ # @overload attributes(names)
39
+ # @param names [Array<String, Symbol>]
40
+ # @param name [String, Symbol]
41
+ def self.attributes(*names)
42
+ self.attribute_names |= names.map(&:to_sym)
43
+ # Silence redefinition of methods warnings
44
+ ActiveModelSerializers.silence_warnings do
45
+ attr_accessor(*names)
46
+ end
47
+ end
48
+
49
+ # Opt-in to breaking change
50
+ def self.derive_attributes_from_names_and_fix_accessors
51
+ unless included_modules.include?(DeriveAttributesFromNamesAndFixAccessors)
52
+ prepend(DeriveAttributesFromNamesAndFixAccessors)
53
+ end
54
+ end
55
+
56
+ module DeriveAttributesFromNamesAndFixAccessors
57
+ def self.included(base)
58
+ # NOTE that +id+ will always be in +attributes+.
59
+ base.attributes :id
60
+ end
61
+
62
+ # Override the +attributes+ method so that the hash is derived from +attribute_names+.
63
+ #
64
+ # The fields in +attribute_names+ determines the returned hash.
65
+ # +attributes+ are returned frozen to prevent any expectations that mutation affects
66
+ # the actual values in the model.
67
+ def attributes
68
+ self.class.attribute_names.each_with_object({}) do |attribute_name, result|
69
+ result[attribute_name] = public_send(attribute_name).freeze
70
+ end.with_indifferent_access.freeze
71
+ end
72
+ end
73
+
74
+ # Support for validation and other ActiveModel::Errors
75
+ # @return [ActiveModel::Errors]
76
+ attr_reader :errors
77
+
78
+ # (see #updated_at)
79
+ attr_writer :updated_at
80
+
81
+ # The only way to change the attributes of an instance is to directly mutate the attributes.
82
+ # @example
83
+ #
84
+ # model.attributes[:foo] = :bar
85
+ # @return [Hash]
86
+ attr_reader :attributes
87
+
88
+ # @param attributes [Hash]
89
+ def initialize(attributes = {})
90
+ attributes ||= {} # protect against nil
91
+ @attributes = attributes.symbolize_keys.with_indifferent_access
92
+ @errors = ActiveModel::Errors.new(self)
93
+ super
94
+ end
95
+
96
+ # Defaults to the downcased model name.
97
+ # This probably isn't a good default, since it's not a unique instance identifier,
98
+ # but that's what is currently implemented \_('-')_/.
99
+ #
100
+ # @note Though +id+ is defined, it will only show up
101
+ # in +attributes+ when it is passed in to the initializer or added to +attributes+,
102
+ # such as <tt>attributes[:id] = 5</tt>.
103
+ # @return [String, Numeric, Symbol]
104
+ def id
105
+ attributes.fetch(:id) do
106
+ defined?(@id) ? @id : self.class.model_name.name && self.class.model_name.name.downcase
107
+ end
108
+ end
109
+
110
+ # When not set, defaults to the time the file was modified.
111
+ #
112
+ # @note Though +updated_at+ and +updated_at=+ are defined, it will only show up
113
+ # in +attributes+ when it is passed in to the initializer or added to +attributes+,
114
+ # such as <tt>attributes[:updated_at] = Time.current</tt>.
115
+ # @return [String, Numeric, Time]
116
+ def updated_at
117
+ attributes.fetch(:updated_at) do
118
+ defined?(@updated_at) ? @updated_at : File.mtime(__FILE__)
119
+ end
120
+ end
121
+
122
+ # To customize model behavior, this method must be redefined. However,
123
+ # there are other ways of setting the +cache_key+ a serializer uses.
124
+ # @return [String]
125
+ def cache_key
126
+ ActiveSupport::Cache.expand_cache_key([
127
+ self.class.model_name.name.downcase,
128
+ "#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}"
129
+ ].compact)
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+ require 'action_controller'
5
+ require 'action_controller/railtie'
6
+ require 'action_controller/serialization'
7
+
8
+ module ActiveModelSerializers
9
+ class Railtie < Rails::Railtie
10
+ config.eager_load_namespaces << ActiveModelSerializers
11
+
12
+ config.to_prepare do
13
+ ActiveModel::Serializer.serializers_cache.clear
14
+ end
15
+
16
+ initializer 'active_model_serializers.action_controller' do
17
+ ActiveSupport.on_load(:action_controller) do
18
+ include(::ActionController::Serialization)
19
+ end
20
+ end
21
+
22
+ initializer 'active_model_serializers.prepare_serialization_context' do
23
+ SerializationContext.url_helpers = Rails.application.routes.url_helpers
24
+ SerializationContext.default_url_options = Rails.application.routes.default_url_options
25
+ end
26
+
27
+ # This hook is run after the action_controller railtie has set the configuration
28
+ # based on the *environment* configuration and before any config/initializers are run
29
+ # and also before eager_loading (if enabled).
30
+ initializer 'active_model_serializers.set_configs', after: 'action_controller.set_configs' do
31
+ ActiveModelSerializers.logger = Rails.configuration.action_controller.logger
32
+ ActiveModelSerializers.config.perform_caching = Rails.configuration.action_controller.perform_caching
33
+ # We want this hook to run after the config has been set, even if ActionController has already loaded.
34
+ ActiveSupport.on_load(:action_controller) do
35
+ ActiveModelSerializers.config.cache_store = ActionController::Base.cache_store
36
+ end
37
+ end
38
+
39
+ # :nocov:
40
+ generators do |app|
41
+ Rails::Generators.configure!(app.config.generators)
42
+ Rails::Generators.hidden_namespaces.uniq!
43
+ require 'generators/rails/resource_override'
44
+ end
45
+ # :nocov:
46
+
47
+ def extend_action_controller_test_case(&block)
48
+ if Rails::VERSION::MAJOR >= 6 || Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2
49
+ ActiveSupport.on_load(:action_controller_test_case, run_once: true, &block)
50
+ else
51
+ ActionController::TestCase.instance_eval(&block)
52
+ end
53
+ end
54
+
55
+ if Rails.env.test?
56
+ extend_action_controller_test_case do
57
+ include ActiveModelSerializers::Test::Schema
58
+ include ActiveModelSerializers::Test::Serializer
59
+ end
60
+ end
61
+ end
62
+ end