|
3 | 3 | # serializable non-activerecord objects.
|
4 | 4 | module ActiveModelSerializers
|
5 | 5 | class Model
|
6 |
| - include ActiveModel::Model |
7 | 6 | include ActiveModel::Serializers::JSON
|
| 7 | + include ActiveModel::Model |
| 8 | + |
| 9 | + class_attribute :attribute_names |
| 10 | + # Initialize +attribute_names+ for all subclasses. The array is usually |
| 11 | + # mutated in the +attributes+ method, but can be set directly, as well. |
| 12 | + self.attribute_names = [] |
8 | 13 |
|
9 | 14 | def self.attributes(*names)
|
10 |
| - attr_accessor(*names) |
| 15 | + self.attribute_names |= names.map(&:to_sym) |
| 16 | + # Silence redefinition of methods warnings |
| 17 | + ActiveModelSerializers.silence_warnings do |
| 18 | + attr_accessor(*names) |
| 19 | + end |
11 | 20 | end
|
12 | 21 |
|
13 |
| - attr_reader :attributes, :errors |
| 22 | + attr_reader :errors |
| 23 | + # NOTE that +updated_at+ isn't included in +attribute_names+, |
| 24 | + # which means it won't show up in +attributes+ unless a subclass has |
| 25 | + # either <tt>attributes :updated_at</tt> which will redefine the methods |
| 26 | + # or <tt>attribute_names << :updated_at</tt>. |
| 27 | + attr_writer :updated_at |
| 28 | + # NOTE that +id+ will always be in +attributes+. |
| 29 | + attributes :id |
14 | 30 |
|
15 | 31 | def initialize(attributes = {})
|
16 |
| - @attributes = attributes && attributes.symbolize_keys |
17 | 32 | @errors = ActiveModel::Errors.new(self)
|
18 | 33 | super
|
19 | 34 | end
|
20 | 35 |
|
21 |
| - # Defaults to the downcased model name. |
22 |
| - def id |
23 |
| - attributes.fetch(:id) { self.class.name.downcase } |
| 36 | + # The the fields in +attribute_names+ determines the returned hash. |
| 37 | + # +attributes+ are returned frozen to prevent any expectations that mutation affects |
| 38 | + # the actual values in the model. |
| 39 | + def attributes |
| 40 | + attribute_names.each_with_object({}) do |attribute_name, result| |
| 41 | + result[attribute_name] = public_send(attribute_name).freeze |
| 42 | + end.with_indifferent_access.freeze |
24 | 43 | end
|
25 | 44 |
|
26 |
| - # Defaults to the downcased model name and updated_at |
| 45 | + # To customize model behavior, this method must be redefined. However, |
| 46 | + # there are other ways of setting the +cache_key+ a serializer uses. |
27 | 47 | def cache_key
|
28 |
| - attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}" } |
| 48 | + ActiveSupport::Cache.expand_cache_key([ |
| 49 | + self.class.model_name.name.downcase, |
| 50 | + "#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}" |
| 51 | + ].compact) |
29 | 52 | end
|
30 | 53 |
|
31 |
| - # Defaults to the time the serializer file was modified. |
| 54 | + # When no set, defaults to the time the file was modified. |
| 55 | + # See NOTE by attr_writer :updated_at |
32 | 56 | def updated_at
|
33 |
| - attributes.fetch(:updated_at) { File.mtime(__FILE__) } |
34 |
| - end |
35 |
| - |
36 |
| - def read_attribute_for_serialization(key) |
37 |
| - if key == :id || key == 'id' |
38 |
| - attributes.fetch(key) { id } |
39 |
| - else |
40 |
| - attributes[key] |
41 |
| - end |
| 57 | + defined?(@updated_at) ? @updated_at : File.mtime(__FILE__) |
42 | 58 | end
|
43 | 59 |
|
44 | 60 | # The following methods are needed to be minimally implemented for ActiveModel::Errors
|
|
0 commit comments