Class: ActiveModel::Serializer::Reflection

Inherits:
Field
  • Object
show all
Defined in:
lib/active_model/serializer/reflection.rb

Overview

Holds all the meta-data about an association as it was specified in the ActiveModel::Serializer class.

Specifically, the association 'comments' is evaluated two different ways:
1) as 'comments' and named 'comments'.
2) as 'object.comments.last(1)' and named 'last_comments'.

PostSerializer._reflections #=>
  # [
  #   HasOneReflection.new(:author, serializer: AuthorSerializer),
  #   HasManyReflection.new(:comments)
  #   HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
  #   HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
  # ]

So you can inspect reflections in your Adapters.

Examples:

class PostSerializer < ActiveModel::Serializer
  has_one :author, serializer: AuthorSerializer
  has_many :comments
  has_many :comments, key: :last_comments do
    object.comments.last(1)
  end
  has_many :secret_meta_data, if: :is_admin?

  def is_admin?
    current_user.admin?
  end
end

Direct Known Subclasses

CollectionReflection, SingularReflection

Instance Attribute Summary

Attributes inherited from Field

#block, #name, #options

Instance Method Summary collapse

Methods inherited from Field

#excluded?

Constructor Details

#initializeReflection

Returns a new instance of Reflection.



37
38
39
40
41
42
# File 'lib/active_model/serializer/reflection.rb', line 37

def initialize(*)
  super
  @_links = {}
  @_include_data = Serializer.config.include_data_default
  @_meta = nil
end

Instance Method Details

#build_association(parent_serializer, parent_serializer_options, include_slice = {}) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Build association. This method is used internally to build serializer’s association by its reflection.

Examples:

# Given the following serializer defined:
class PostSerializer < ActiveModel::Serializer
  has_many :comments, serializer: CommentSummarySerializer
end

# Then you instantiate your serializer
post_serializer = PostSerializer.new(post, foo: 'bar') #
# to build association for comments you need to get reflection
comments_reflection = PostSerializer._reflections.detect { |r| r.name == :comments }
# and #build_association
comments_reflection.build_association(post_serializer, foo: 'bar')

Parameters:

  • parent_serializer (Serializer)

    for given association

  • parent_serializer_options (Hash{Symbol => Object})


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/active_model/serializer/reflection.rb', line 107

def build_association(parent_serializer, parent_serializer_options, include_slice = {})
  reflection_options = options.dup

  # Pass the parent's namespace onto the child serializer
  reflection_options[:namespace] ||= parent_serializer_options[:namespace]

  association_value = value(parent_serializer, include_slice)
  serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
  reflection_options[:include_data] = include_data?(include_slice)
  reflection_options[:links] = @_links
  reflection_options[:meta] = @_meta

  if serializer_class
    serializer = catch(:no_serializer) do
      serializer_class.new(
        association_value,
        serializer_options(parent_serializer, parent_serializer_options, reflection_options)
      )
    end
    if serializer.nil?
      reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
    else
      reflection_options[:serializer] = serializer
    end
  elsif !association_value.nil? && !association_value.instance_of?(Object)
    reflection_options[:virtual_value] = association_value
  end

  block = nil
  Association.new(name, reflection_options, block)
end

#include_data(value = true) ⇒ Object



54
55
56
57
# File 'lib/active_model/serializer/reflection.rb', line 54

def include_data(value = true)
  @_include_data = value
  :nil
end


44
45
46
47
# File 'lib/active_model/serializer/reflection.rb', line 44

def link(name, value = nil, &block)
  @_links[name] = block || value
  :nil
end

#meta(value = nil, &block) ⇒ Object



49
50
51
52
# File 'lib/active_model/serializer/reflection.rb', line 49

def meta(value = nil, &block)
  @_meta = block || value
  :nil
end

#value(serializer, include_slice) {|ActiveModel::Serializer| ... } ⇒ :nil, associated resource or resource collection

Examples:

has_one :blog do |serializer|
  serializer.cached_blog
end

def cached_blog
  cache_store.fetch("cached_blog:#{object.updated_at}") do
    Blog.find(object.blog_id)
  end
end

Parameters:

Yields:

Returns:

  • (:nil, associated resource or resource collection)


72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/active_model/serializer/reflection.rb', line 72

def value(serializer, include_slice)
  @object = serializer.object
  @scope = serializer.scope

  block_value = instance_exec(serializer, &block) if block
  return unless include_data?(include_slice)

  if block && block_value != :nil
    block_value
  else
    serializer.read_attribute_for_serialization(name)
  end
end