active_model_serializers_rails_2.3 0.9.0.alpha1
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.
- data/CHANGELOG.md +87 -0
- data/CONTRIBUTING.md +20 -0
- data/DESIGN.textile +586 -0
- data/MIT-LICENSE +21 -0
- data/README.md +793 -0
- data/lib/active_model/array_serializer.rb +60 -0
- data/lib/active_model/default_serializer.rb +27 -0
- data/lib/active_model/serializable.rb +25 -0
- data/lib/active_model/serializer.rb +220 -0
- data/lib/active_model/serializer/associations.rb +98 -0
- data/lib/active_model/serializer/config.rb +31 -0
- data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
- data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
- data/lib/active_model/serializer/railtie.rb +10 -0
- data/lib/active_model/serializer/version.rb +5 -0
- data/lib/active_model/serializer_support.rb +5 -0
- data/lib/active_model_serializers.rb +33 -0
- data/test/coverage_setup.rb +15 -0
- data/test/fixtures/active_record.rb +92 -0
- data/test/fixtures/poro.rb +64 -0
- data/test/integration/active_record/active_record_test.rb +77 -0
- data/test/test_app.rb +11 -0
- data/test/test_helper.rb +13 -0
- data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
- data/test/unit/active_model/array_serializer/root_test.rb +102 -0
- data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
- data/test/unit/active_model/array_serializer/serialization_test.rb +182 -0
- data/test/unit/active_model/default_serializer_test.rb +13 -0
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
- data/test/unit/active_model/serializer/associations_test.rb +19 -0
- data/test/unit/active_model/serializer/attributes_test.rb +41 -0
- data/test/unit/active_model/serializer/config_test.rb +86 -0
- data/test/unit/active_model/serializer/filter_test.rb +49 -0
- data/test/unit/active_model/serializer/has_many_test.rb +174 -0
- data/test/unit/active_model/serializer/has_one_test.rb +151 -0
- data/test/unit/active_model/serializer/meta_test.rb +39 -0
- data/test/unit/active_model/serializer/root_test.rb +117 -0
- data/test/unit/active_model/serializer/scope_test.rb +49 -0
- metadata +127 -0
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            require 'active_model/default_serializer'
         | 
| 2 | 
            +
            require 'active_model/serializable'
         | 
| 3 | 
            +
            require 'active_model/serializer'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module ActiveModel
         | 
| 6 | 
            +
              class ArraySerializer
         | 
| 7 | 
            +
                include Serializable
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                class << self
         | 
| 10 | 
            +
                  attr_accessor :_root
         | 
| 11 | 
            +
                  alias root  _root=
         | 
| 12 | 
            +
                  alias root= _root=
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize(object, options={})
         | 
| 16 | 
            +
                  @object          = object
         | 
| 17 | 
            +
                  @scope           = options[:scope]
         | 
| 18 | 
            +
                  @root            = options.fetch(:root, self.class._root)
         | 
| 19 | 
            +
                  @meta_key        = options[:meta_key] || :meta
         | 
| 20 | 
            +
                  @meta            = options[@meta_key]
         | 
| 21 | 
            +
                  @each_serializer = options[:each_serializer]
         | 
| 22 | 
            +
                  @resource_name   = options[:resource_name]
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                attr_accessor :object, :scope, :root, :meta_key, :meta
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def json_key
         | 
| 27 | 
            +
                  if root.nil?
         | 
| 28 | 
            +
                    @resource_name
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    root
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def serializer_for(item)
         | 
| 35 | 
            +
                  serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
         | 
| 36 | 
            +
                  serializer_class.new(item, scope: scope)
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def serializable_object
         | 
| 40 | 
            +
                  @object.map do |item|
         | 
| 41 | 
            +
                    serializer_for(item).serializable_object
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                alias_method :serializable_array, :serializable_object
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def embedded_in_root_associations
         | 
| 47 | 
            +
                  @object.each_with_object({}) do |item, hash|
         | 
| 48 | 
            +
                    serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
         | 
| 49 | 
            +
                      next if !objects || objects.flatten.empty?
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      if hash.has_key?(type)
         | 
| 52 | 
            +
                        hash[type].concat(objects).uniq!
         | 
| 53 | 
            +
                      else
         | 
| 54 | 
            +
                        hash[type] = objects
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            require 'active_model/serializable'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ActiveModel
         | 
| 4 | 
            +
              # DefaultSerializer
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              # Provides a constant interface for all items
         | 
| 7 | 
            +
              class DefaultSerializer
         | 
| 8 | 
            +
                include ActiveModel::Serializable
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_reader :object
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize(object, options=nil)
         | 
| 13 | 
            +
                  @object = object
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def as_json(options={})
         | 
| 17 | 
            +
                  return nil if @object.nil?
         | 
| 18 | 
            +
                  if @object.is_a?(Struct)
         | 
| 19 | 
            +
                    Hash[@object.members.zip(@object.values)]
         | 
| 20 | 
            +
                  else
         | 
| 21 | 
            +
                    @object.as_json
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                alias serializable_hash as_json
         | 
| 25 | 
            +
                alias serializable_object as_json
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module ActiveModel
         | 
| 2 | 
            +
              module Serializable
         | 
| 3 | 
            +
                def as_json(options={})
         | 
| 4 | 
            +
                  if root = options.fetch(:root, json_key)
         | 
| 5 | 
            +
                    hash = { root => serializable_object }
         | 
| 6 | 
            +
                    hash.merge!(serializable_data)
         | 
| 7 | 
            +
                    hash
         | 
| 8 | 
            +
                  else
         | 
| 9 | 
            +
                    serializable_object
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def serializable_data
         | 
| 14 | 
            +
                  embedded_in_root_associations.tap do |hash|
         | 
| 15 | 
            +
                    if respond_to?(:meta) && meta
         | 
| 16 | 
            +
                      hash[meta_key] = meta
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def embedded_in_root_associations
         | 
| 22 | 
            +
                  {}
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,220 @@ | |
| 1 | 
            +
            require 'active_record'
         | 
| 2 | 
            +
            require 'active_model/array_serializer'
         | 
| 3 | 
            +
            require 'active_model/serializable'
         | 
| 4 | 
            +
            require 'active_model/serializer/associations'
         | 
| 5 | 
            +
            require 'active_model/serializer/config'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'thread'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module ActiveRecord
         | 
| 10 | 
            +
              class Base
         | 
| 11 | 
            +
                alias read_attribute_for_serialization send
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            module ActiveModel
         | 
| 16 | 
            +
              class Serializer
         | 
| 17 | 
            +
                include Serializable
         | 
| 18 | 
            +
                extend ActiveSupport::Inflector
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                @mutex = Mutex.new
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                class << self
         | 
| 23 | 
            +
                  def inherited(base)
         | 
| 24 | 
            +
                    base._root = _root
         | 
| 25 | 
            +
                    base._attributes = (_attributes || []).dup
         | 
| 26 | 
            +
                    base._associations = (_associations || {}).dup
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                  def const_regexp(camel_cased_word) #:nodoc:
         | 
| 29 | 
            +
                    parts = camel_cased_word.split("::")
         | 
| 30 | 
            +
                    last  = parts.pop
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    parts.reverse.inject(last) do |acc, part|
         | 
| 33 | 
            +
                      part.empty? ? acc : "#{part}(::#{acc})?"
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                  def safe_constantize(camel_cased_word)
         | 
| 37 | 
            +
                    begin
         | 
| 38 | 
            +
                      constantize(camel_cased_word)
         | 
| 39 | 
            +
                    rescue NameError => e
         | 
| 40 | 
            +
                      raise unless e.message =~ /(uninitialized constant|wrong constant name) #{const_regexp(camel_cased_word)}$/ ||
         | 
| 41 | 
            +
                        e.name.to_s == camel_cased_word.to_s
         | 
| 42 | 
            +
                    rescue ArgumentError => e
         | 
| 43 | 
            +
                      raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def setup
         | 
| 48 | 
            +
                    @mutex.synchronize do
         | 
| 49 | 
            +
                      yield CONFIG
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  def embed(type, options={})
         | 
| 54 | 
            +
                    CONFIG.embed = type
         | 
| 55 | 
            +
                    CONFIG.embed_in_root = true if options[:embed_in_root] || options[:include]
         | 
| 56 | 
            +
                    ActiveSupport::Deprecation.warn <<-WARN
         | 
| 57 | 
            +
            ** Notice: embed is deprecated. **
         | 
| 58 | 
            +
            The use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.
         | 
| 59 | 
            +
            Please use the global .setup method instead:
         | 
| 60 | 
            +
            ActiveModel::Serializer.setup do |config|
         | 
| 61 | 
            +
              config.embed = :#{type}
         | 
| 62 | 
            +
              config.embed_in_root = #{CONFIG.embed_in_root || false}
         | 
| 63 | 
            +
            end
         | 
| 64 | 
            +
                    WARN
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  if RUBY_VERSION >= '2.0'
         | 
| 68 | 
            +
                    def serializer_for(resource)
         | 
| 69 | 
            +
                      if resource.respond_to?(:to_ary)
         | 
| 70 | 
            +
                        ArraySerializer
         | 
| 71 | 
            +
                      else
         | 
| 72 | 
            +
                        begin
         | 
| 73 | 
            +
                          Object.const_get "#{resource.class.name}Serializer"
         | 
| 74 | 
            +
                        rescue NameError
         | 
| 75 | 
            +
                          nil
         | 
| 76 | 
            +
                        end
         | 
| 77 | 
            +
                      end
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
                  else
         | 
| 80 | 
            +
                    def serializer_for(resource)
         | 
| 81 | 
            +
                      if resource.respond_to?(:to_ary)
         | 
| 82 | 
            +
                        ArraySerializer
         | 
| 83 | 
            +
                      else
         | 
| 84 | 
            +
                        safe_constantize "#{resource.class.name}Serializer"
         | 
| 85 | 
            +
                      end
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  attr_accessor :_root, :_attributes, :_associations
         | 
| 90 | 
            +
                  alias root  _root=
         | 
| 91 | 
            +
                  alias root= _root=
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def root_name
         | 
| 94 | 
            +
                    name.demodulize.underscore.sub(/_serializer$/, '') if name
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def attributes(*attrs)
         | 
| 98 | 
            +
                    @_attributes.concat attrs
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                    attrs.each do |attr|
         | 
| 101 | 
            +
                      define_method attr do
         | 
| 102 | 
            +
                        object.read_attribute_for_serialization attr
         | 
| 103 | 
            +
                      end unless method_defined?(attr)
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  def has_one(*attrs)
         | 
| 108 | 
            +
                    associate(Association::HasOne, *attrs)
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  def has_many(*attrs)
         | 
| 112 | 
            +
                    associate(Association::HasMany, *attrs)
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  private
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  def associate(klass, *attrs)
         | 
| 118 | 
            +
                    options = attrs.extract_options!
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    attrs.each do |attr|
         | 
| 121 | 
            +
                      define_method attr do
         | 
| 122 | 
            +
                        object.send attr
         | 
| 123 | 
            +
                      end unless method_defined?(attr)
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                      @_associations[attr] = klass.new(attr, options)
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                def initialize(object, options={})
         | 
| 131 | 
            +
                  @object        = object
         | 
| 132 | 
            +
                  @scope         = options[:scope]
         | 
| 133 | 
            +
                  @root          = options.fetch(:root, self.class._root)
         | 
| 134 | 
            +
                  @meta_key      = options[:meta_key] || :meta
         | 
| 135 | 
            +
                  @meta          = options[@meta_key]
         | 
| 136 | 
            +
                  @wrap_in_array = options[:_wrap_in_array]
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
                attr_accessor :object, :scope, :root, :meta_key, :meta
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                def json_key
         | 
| 141 | 
            +
                  if root == true || root.nil?
         | 
| 142 | 
            +
                    self.class.root_name
         | 
| 143 | 
            +
                  else
         | 
| 144 | 
            +
                    root
         | 
| 145 | 
            +
                  end
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                def attributes
         | 
| 149 | 
            +
                  filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
         | 
| 150 | 
            +
                    hash[name] = send(name)
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def associations
         | 
| 155 | 
            +
                  associations = self.class._associations
         | 
| 156 | 
            +
                  included_associations = filter(associations.keys)
         | 
| 157 | 
            +
                  associations.each_with_object({}) do |(name, association), hash|
         | 
| 158 | 
            +
                    if included_associations.include? name
         | 
| 159 | 
            +
                      if association.embed_ids?
         | 
| 160 | 
            +
                        hash[association.key] = serialize_ids association
         | 
| 161 | 
            +
                      elsif association.embed_objects?
         | 
| 162 | 
            +
                        hash[association.embedded_key] = serialize association
         | 
| 163 | 
            +
                      end
         | 
| 164 | 
            +
                    end
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                def filter(keys)
         | 
| 169 | 
            +
                  keys
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                def embedded_in_root_associations
         | 
| 173 | 
            +
                  associations = self.class._associations
         | 
| 174 | 
            +
                  included_associations = filter(associations.keys)
         | 
| 175 | 
            +
                  associations.each_with_object({}) do |(name, association), hash|
         | 
| 176 | 
            +
                    if included_associations.include? name
         | 
| 177 | 
            +
                      if association.embed_in_root?
         | 
| 178 | 
            +
                        association_serializer = build_serializer(association)
         | 
| 179 | 
            +
                        hash.merge! association_serializer.embedded_in_root_associations
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                        serialized_data = association_serializer.serializable_object
         | 
| 182 | 
            +
                        key = association.root_key
         | 
| 183 | 
            +
                        if hash.has_key?(key)
         | 
| 184 | 
            +
                          hash[key].concat(serialized_data).uniq!
         | 
| 185 | 
            +
                        else
         | 
| 186 | 
            +
                          hash[key] = serialized_data
         | 
| 187 | 
            +
                        end
         | 
| 188 | 
            +
                      end
         | 
| 189 | 
            +
                    end
         | 
| 190 | 
            +
                  end
         | 
| 191 | 
            +
                end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                def build_serializer(association)
         | 
| 194 | 
            +
                  object = send(association.name)
         | 
| 195 | 
            +
                  association.build_serializer(object, scope: scope)
         | 
| 196 | 
            +
                end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                def serialize(association)
         | 
| 199 | 
            +
                  build_serializer(association).serializable_object
         | 
| 200 | 
            +
                end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                def serialize_ids(association)
         | 
| 203 | 
            +
                  associated_data = send(association.name)
         | 
| 204 | 
            +
                  if associated_data.respond_to?(:to_ary)
         | 
| 205 | 
            +
                    associated_data.map { |elem| elem.read_attribute_for_serialization(association.embed_key) }
         | 
| 206 | 
            +
                  else
         | 
| 207 | 
            +
                    associated_data.read_attribute_for_serialization(association.embed_key) if associated_data
         | 
| 208 | 
            +
                  end
         | 
| 209 | 
            +
                end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                def serializable_object(options={})
         | 
| 212 | 
            +
                  return nil if object.nil?
         | 
| 213 | 
            +
                  hash = attributes
         | 
| 214 | 
            +
                  hash.merge! associations
         | 
| 215 | 
            +
                  @wrap_in_array ? [hash] : hash
         | 
| 216 | 
            +
                end
         | 
| 217 | 
            +
                alias_method :serializable_hash, :serializable_object
         | 
| 218 | 
            +
              end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
            end
         | 
| @@ -0,0 +1,98 @@ | |
| 1 | 
            +
            require 'active_model/default_serializer'
         | 
| 2 | 
            +
            require 'active_model/serializer'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module ActiveModel
         | 
| 5 | 
            +
              class Serializer
         | 
| 6 | 
            +
                class Association
         | 
| 7 | 
            +
                  def initialize(name, options={})
         | 
| 8 | 
            +
                    if options.has_key?(:include)
         | 
| 9 | 
            +
                      ActiveSupport::Deprecation.warn <<-WARN
         | 
| 10 | 
            +
            ** Notice: include was renamed to embed_in_root. **
         | 
| 11 | 
            +
                      WARN
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    @name          = name.to_s
         | 
| 15 | 
            +
                    @options       = options
         | 
| 16 | 
            +
                    self.embed     = options.fetch(:embed) { CONFIG.embed }
         | 
| 17 | 
            +
                    @embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
         | 
| 18 | 
            +
                    @embed_key     = options[:embed_key] || :id
         | 
| 19 | 
            +
                    @key           = options[:key]
         | 
| 20 | 
            +
                    @embedded_key  = options[:root] || name
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    serializer = @options[:serializer]
         | 
| 23 | 
            +
                    @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  attr_reader :name, :embed_ids, :embed_objects
         | 
| 27 | 
            +
                  attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options
         | 
| 28 | 
            +
                  alias embed_ids? embed_ids
         | 
| 29 | 
            +
                  alias embed_objects? embed_objects
         | 
| 30 | 
            +
                  alias embed_in_root? embed_in_root
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def embed=(embed)
         | 
| 33 | 
            +
                    @embed_ids     = embed == :id || embed == :ids
         | 
| 34 | 
            +
                    @embed_objects = embed == :object || embed == :objects
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def serializer_from_object(object)
         | 
| 38 | 
            +
                    Serializer.serializer_for(object)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def default_serializer
         | 
| 42 | 
            +
                    DefaultSerializer
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def build_serializer(object, options = {})
         | 
| 46 | 
            +
                    serializer_class(object).new(object, options.merge(self.options))
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  class HasOne < Association
         | 
| 50 | 
            +
                    def initialize(name, *args)
         | 
| 51 | 
            +
                      super
         | 
| 52 | 
            +
                      @root_key = @embedded_key.to_s.pluralize
         | 
| 53 | 
            +
                      @key ||= "#{name}_id"
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    def serializer_class(object)
         | 
| 57 | 
            +
                      serializer_from_options || serializer_from_object(object) || default_serializer
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    def build_serializer(object, options = {})
         | 
| 61 | 
            +
                      options[:_wrap_in_array] = embed_in_root?
         | 
| 62 | 
            +
                      super
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  class HasMany < Association
         | 
| 67 | 
            +
                    def initialize(name, *args)
         | 
| 68 | 
            +
                      super
         | 
| 69 | 
            +
                      @root_key = @embedded_key
         | 
| 70 | 
            +
                      @key ||= "#{name.to_s.singularize}_ids"
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    def serializer_class(object)
         | 
| 74 | 
            +
                      if use_array_serializer?
         | 
| 75 | 
            +
                        ArraySerializer
         | 
| 76 | 
            +
                      else
         | 
| 77 | 
            +
                        serializer_from_options
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    def options
         | 
| 82 | 
            +
                      if use_array_serializer?
         | 
| 83 | 
            +
                        { each_serializer: serializer_from_options }.merge! super
         | 
| 84 | 
            +
                      else
         | 
| 85 | 
            +
                        super
         | 
| 86 | 
            +
                      end
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    private
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                    def use_array_serializer?
         | 
| 92 | 
            +
                      !serializer_from_options ||
         | 
| 93 | 
            +
                        serializer_from_options && !(serializer_from_options <= ArraySerializer)
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module ActiveModel
         | 
| 2 | 
            +
              class Serializer
         | 
| 3 | 
            +
                class Config
         | 
| 4 | 
            +
                  def initialize(data = {})
         | 
| 5 | 
            +
                    @data = data
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def each(&block)
         | 
| 9 | 
            +
                    @data.each(&block)
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def clear
         | 
| 13 | 
            +
                    @data.clear
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def method_missing(name, *args)
         | 
| 17 | 
            +
                    name = name.to_s
         | 
| 18 | 
            +
                    return @data[name] if @data.include?(name)
         | 
| 19 | 
            +
                    match = name.match(/\A(.*?)([?=]?)\Z/)
         | 
| 20 | 
            +
                    case match[2]
         | 
| 21 | 
            +
                    when "="
         | 
| 22 | 
            +
                      @data[match[1]] = args.first
         | 
| 23 | 
            +
                    when "?"
         | 
| 24 | 
            +
                      !!@data[match[1]]
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                CONFIG = Config.new('embed' => :objects) # :nodoc:
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         |