fast_serializer_ruby 0.2.1 → 0.6.3
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +4 -2
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +18 -1
- data/Gemfile.lock +53 -42
- data/LICENSE.txt +1 -1
- data/README.md +45 -33
- data/fast_serializer.gemspec +6 -13
- data/lib/fast_serializer.rb +2 -1
- data/lib/fast_serializer/configuration.rb +14 -2
- data/lib/fast_serializer/json_model/array.rb +6 -2
- data/lib/fast_serializer/json_model/attribute.rb +109 -15
- data/lib/fast_serializer/json_model/has_many_relationship.rb +5 -3
- data/lib/fast_serializer/json_model/has_one_relationship.rb +4 -1
- data/lib/fast_serializer/json_model/node.rb +11 -3
- data/lib/fast_serializer/json_model/object.rb +16 -6
- data/lib/fast_serializer/json_model/relationship.rb +31 -4
- data/lib/fast_serializer/schema.rb +107 -105
- data/lib/fast_serializer/schema/mixin.rb +71 -0
- data/lib/fast_serializer/utils.rb +17 -0
- data/lib/fast_serializer/version.rb +1 -1
- metadata +11 -134
| @@ -3,7 +3,11 @@ | |
| 3 3 | 
             
            module FastSerializer
         | 
| 4 4 | 
             
              module JsonModel
         | 
| 5 5 | 
             
                class Array < Relationship
         | 
| 6 | 
            -
                   | 
| 6 | 
            +
                  # @param resource [Object]
         | 
| 7 | 
            +
                  # @param params [Hash]
         | 
| 8 | 
            +
                  # @param context [Hash]
         | 
| 9 | 
            +
                  # @return [Array]
         | 
| 10 | 
            +
                  def serialize(resources, params, context)
         | 
| 7 11 | 
             
                    return if resources.nil?
         | 
| 8 12 |  | 
| 9 13 | 
             
                    if @serializer_klass
         | 
| @@ -13,7 +17,7 @@ module FastSerializer | |
| 13 17 | 
             
                    end
         | 
| 14 18 | 
             
                  end
         | 
| 15 19 |  | 
| 16 | 
            -
                  def included?( | 
| 20 | 
            +
                  def included?(*)
         | 
| 17 21 | 
             
                    true
         | 
| 18 22 | 
             
                  end
         | 
| 19 23 | 
             
                end
         | 
| @@ -3,32 +3,126 @@ | |
| 3 3 | 
             
            module FastSerializer
         | 
| 4 4 | 
             
              module JsonModel
         | 
| 5 5 | 
             
                class Attribute < Node
         | 
| 6 | 
            -
                   | 
| 7 | 
            -
             | 
| 6 | 
            +
                  attr_accessor :mixin,
         | 
| 7 | 
            +
                                :method_name,
         | 
| 8 | 
            +
                                :method_arity,
         | 
| 9 | 
            +
                                :cond,
         | 
| 10 | 
            +
                                :cond_arity,
         | 
| 11 | 
            +
                                :cond_method_name,
         | 
| 12 | 
            +
                                :injected
         | 
| 8 13 |  | 
| 9 | 
            -
             | 
| 14 | 
            +
                  def initialize(*)
         | 
| 15 | 
            +
                    super
         | 
| 10 16 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 17 | 
            +
                    @mixin = nil
         | 
| 18 | 
            +
                    @method_name = nil
         | 
| 19 | 
            +
                    @injected = false
         | 
| 20 | 
            +
                    @cond_method_name = nil
         | 
| 21 | 
            +
                    @cond = nil
         | 
| 22 | 
            +
                    @cond = @opts[:if] || @opts[:unless] || @cond
         | 
| 16 23 |  | 
| 17 | 
            -
                     | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 24 | 
            +
                    init_with_proc if method.is_a?(Proc)
         | 
| 25 | 
            +
                    init_with_cond if !cond.nil? && cond.is_a?(Proc)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def injectable?
         | 
| 29 | 
            +
                    !mixin.nil?
         | 
| 20 30 | 
             
                  end
         | 
| 21 31 |  | 
| 22 | 
            -
                  def  | 
| 23 | 
            -
                     | 
| 32 | 
            +
                  def inject(context)
         | 
| 33 | 
            +
                    context.include(mixin)
         | 
| 34 | 
            +
                    self.injected = true
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  # @param resource [Object]
         | 
| 38 | 
            +
                  # @param params [Hash]
         | 
| 39 | 
            +
                  # @param context [Hash]
         | 
| 40 | 
            +
                  # @return [Object]
         | 
| 41 | 
            +
                  def serialize(resource, params, context)
         | 
| 42 | 
            +
                    can_execute_on_mixin = injected && !method_name.nil? && !context.nil?
         | 
| 24 43 |  | 
| 25 | 
            -
                     | 
| 44 | 
            +
                    val = if can_execute_on_mixin
         | 
| 45 | 
            +
                            call_method_on_context(context, method_name, method_arity, resource, params)
         | 
| 46 | 
            +
                          elsif method.is_a?(Proc)
         | 
| 47 | 
            +
                            call_proc_binding_to_context(context, method, method_arity, resource, params)
         | 
| 48 | 
            +
                          else
         | 
| 49 | 
            +
                            resource.public_send(method)
         | 
| 50 | 
            +
                          end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    val.freeze
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    val
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  # @param resource [Object]
         | 
| 58 | 
            +
                  # @param params [Hash]
         | 
| 59 | 
            +
                  # @param context [Hash]
         | 
| 60 | 
            +
                  # @return [Boolean]
         | 
| 61 | 
            +
                  def included?(resource, params, context)
         | 
| 62 | 
            +
                    return true if cond.nil?
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    can_execute_on_mixin = injected && !cond_method_name.nil? && !context.nil?
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    res = if can_execute_on_mixin
         | 
| 67 | 
            +
                            call_method_on_context(context, cond_method_name, cond_arity, resource, params)
         | 
| 68 | 
            +
                          elsif cond.is_a?(Proc)
         | 
| 69 | 
            +
                            call_proc_binding_to_context(context, cond, cond_arity, resource, params)
         | 
| 70 | 
            +
                          else
         | 
| 71 | 
            +
                            context.public_send(cond)
         | 
| 72 | 
            +
                          end
         | 
| 26 73 |  | 
| 27 | 
            -
                    res = context.instance_exec(resource, params, &cond)
         | 
| 28 74 | 
             
                    res = !res unless @opts[:unless].nil?
         | 
| 29 75 |  | 
| 30 76 | 
             
                    res
         | 
| 31 77 | 
             
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  private
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def init_with_cond
         | 
| 82 | 
            +
                    @cond_method_name = "__#{key}_cond__"
         | 
| 83 | 
            +
                    @cond_arity = cond.arity.abs
         | 
| 84 | 
            +
                    @mixin ||= Module.new
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    if RUBY_VERSION <= '2.5.0'
         | 
| 87 | 
            +
                      @mixin.redefine_method @cond_method_name, &cond
         | 
| 88 | 
            +
                    else
         | 
| 89 | 
            +
                      @mixin.define_method @cond_method_name, &cond
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def init_with_proc
         | 
| 94 | 
            +
                    @method_name = "__#{key}__"
         | 
| 95 | 
            +
                    @method_arity = method.arity.abs
         | 
| 96 | 
            +
                    @mixin = Module.new
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    if RUBY_VERSION <= '2.5.0'
         | 
| 99 | 
            +
                      @mixin.redefine_method @method_name, &method
         | 
| 100 | 
            +
                    else
         | 
| 101 | 
            +
                      @mixin.define_method @method_name, &method
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  def call_proc_binding_to_context(context, prc, arity, resource, params)
         | 
| 106 | 
            +
                    case arity
         | 
| 107 | 
            +
                    when 1
         | 
| 108 | 
            +
                      context.instance_exec(resource, &prc)
         | 
| 109 | 
            +
                    when 2
         | 
| 110 | 
            +
                      context.instance_exec(resource, params, &prc)
         | 
| 111 | 
            +
                    when 0
         | 
| 112 | 
            +
                      context.instance_exec(&prc)
         | 
| 113 | 
            +
                    end
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  def call_method_on_context(context, method_name, arity, resource, params)
         | 
| 117 | 
            +
                    case arity
         | 
| 118 | 
            +
                    when 0
         | 
| 119 | 
            +
                      context.public_send(method_name)
         | 
| 120 | 
            +
                    when 1
         | 
| 121 | 
            +
                      context.public_send(method_name, resource)
         | 
| 122 | 
            +
                    when 2
         | 
| 123 | 
            +
                      context.public_send(method_name, resource, params)
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
                  end
         | 
| 32 126 | 
             
                end
         | 
| 33 127 | 
             
              end
         | 
| 34 128 | 
             
            end
         | 
| @@ -3,16 +3,18 @@ | |
| 3 3 | 
             
            module FastSerializer
         | 
| 4 4 | 
             
              module JsonModel
         | 
| 5 5 | 
             
                class HasManyRelationship < Relationship
         | 
| 6 | 
            -
                   | 
| 6 | 
            +
                  # @param resource [Object]
         | 
| 7 | 
            +
                  # @param params [Hash]
         | 
| 8 | 
            +
                  # @return [Array<Hash>]
         | 
| 9 | 
            +
                  def serialize(resource, params, _context)
         | 
| 7 10 | 
             
                    collection = resource.public_send(method)
         | 
| 8 11 | 
             
                    return if collection.nil?
         | 
| 9 12 |  | 
| 10 13 | 
             
                    if @serializer_klass
         | 
| 11 14 | 
             
                      @serializer_klass.new(collection, params).serializable_hash
         | 
| 12 15 | 
             
                    elsif @schema
         | 
| 13 | 
            -
                      collection.map { | | 
| 16 | 
            +
                      collection.map { |entry| @schema.serialize_resource(entry, params) }
         | 
| 14 17 | 
             
                    end
         | 
| 15 | 
            -
             | 
| 16 18 | 
             
                  end
         | 
| 17 19 | 
             
                end
         | 
| 18 20 | 
             
              end
         | 
| @@ -3,7 +3,10 @@ | |
| 3 3 | 
             
            module FastSerializer
         | 
| 4 4 | 
             
              module JsonModel
         | 
| 5 5 | 
             
                class HasOneRelationship < Relationship
         | 
| 6 | 
            -
                   | 
| 6 | 
            +
                  # @param resource [Object]
         | 
| 7 | 
            +
                  # @param params [Hash]
         | 
| 8 | 
            +
                  # @return [Hash]
         | 
| 9 | 
            +
                  def serialize(resource, params, _)
         | 
| 7 10 | 
             
                    relation = resource.public_send(method)
         | 
| 8 11 |  | 
| 9 12 | 
             
                    if @serializer_klass
         | 
| @@ -5,17 +5,25 @@ module FastSerializer | |
| 5 5 | 
             
                class Node
         | 
| 6 6 | 
             
                  attr_accessor :key, :method, :context
         | 
| 7 7 |  | 
| 8 | 
            +
                  # @param key [String]
         | 
| 9 | 
            +
                  # @param method [String]
         | 
| 10 | 
            +
                  # @param opts [Hash]
         | 
| 8 11 | 
             
                  def initialize(key: nil, method: nil, opts: {}, **_)
         | 
| 9 | 
            -
                    @key = key
         | 
| 12 | 
            +
                    @key = key&.to_sym
         | 
| 10 13 | 
             
                    @method = method || key
         | 
| 11 14 | 
             
                    @opts = opts || {}
         | 
| 12 15 | 
             
                  end
         | 
| 13 16 |  | 
| 14 | 
            -
                   | 
| 17 | 
            +
                  # @return [Boolean]
         | 
| 18 | 
            +
                  def injectable?
         | 
| 19 | 
            +
                    false
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def serialize(_resource, _params, _context = nil)
         | 
| 15 23 | 
             
                    raise NotImplementedError
         | 
| 16 24 | 
             
                  end
         | 
| 17 25 |  | 
| 18 | 
            -
                  def included?(_resource, _params | 
| 26 | 
            +
                  def included?(_resource, _params, _context = nil)
         | 
| 19 27 | 
             
                    raise NotImplementedError
         | 
| 20 28 | 
             
                  end
         | 
| 21 29 | 
             
                end
         | 
| @@ -5,27 +5,37 @@ module FastSerializer | |
| 5 5 | 
             
                class Object < Node
         | 
| 6 6 | 
             
                  attr_accessor :attributes
         | 
| 7 7 |  | 
| 8 | 
            -
                  def initialize( | 
| 8 | 
            +
                  def initialize(args = {})
         | 
| 9 9 | 
             
                    super
         | 
| 10 10 | 
             
                    @attributes = {}
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 |  | 
| 13 | 
            +
                  # @param attribute [FastSerializer::JsonModel::Node]
         | 
| 13 14 | 
             
                  def add_attribute(attribute)
         | 
| 14 15 | 
             
                    attributes[attribute.key] = attribute
         | 
| 15 16 | 
             
                  end
         | 
| 16 17 |  | 
| 17 | 
            -
                   | 
| 18 | 
            +
                  # @param resource [Object]
         | 
| 19 | 
            +
                  # @param params [Hash]
         | 
| 20 | 
            +
                  # @param context [Hash]
         | 
| 21 | 
            +
                  # @return [Hash]
         | 
| 22 | 
            +
                  def serialize(resource, params, context)
         | 
| 18 23 | 
             
                    return if resource.nil?
         | 
| 19 24 |  | 
| 20 | 
            -
                     | 
| 21 | 
            -
             | 
| 25 | 
            +
                    result = {}
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    attributes.each do |_, attribute|
         | 
| 28 | 
            +
                      next unless attribute.included?(resource, params, context)
         | 
| 22 29 |  | 
| 23 30 | 
             
                      val = attribute.serialize(resource, params, context)
         | 
| 24 | 
            -
                       | 
| 31 | 
            +
                      result[attribute.key] = val
         | 
| 25 32 | 
             
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    result
         | 
| 26 35 | 
             
                  end
         | 
| 27 36 |  | 
| 28 | 
            -
                   | 
| 37 | 
            +
                  # @return [Boolean]
         | 
| 38 | 
            +
                  def included?(*)
         | 
| 29 39 | 
             
                    true
         | 
| 30 40 | 
             
                  end
         | 
| 31 41 | 
             
                end
         | 
| @@ -5,22 +5,49 @@ module FastSerializer | |
| 5 5 | 
             
                class Relationship < Attribute
         | 
| 6 6 | 
             
                  attr_accessor :serialization_schema
         | 
| 7 7 |  | 
| 8 | 
            -
                   | 
| 8 | 
            +
                  # @param serializer [FastSerializer::Schema::Mixin]
         | 
| 9 | 
            +
                  # @param schema [FastSerializer::Schema]
         | 
| 10 | 
            +
                  def initialize(serializer: nil, schema: nil, **)
         | 
| 9 11 | 
             
                    super
         | 
| 12 | 
            +
             | 
| 10 13 | 
             
                    @serializer_klass = serializer
         | 
| 11 14 | 
             
                    @schema = schema
         | 
| 12 15 |  | 
| 13 | 
            -
                     | 
| 16 | 
            +
                    if @serializer_klass.nil? && @schema.nil?
         | 
| 17 | 
            +
                      raise ArgumentError, 'must provide serializer or schema'
         | 
| 18 | 
            +
                    end
         | 
| 14 19 | 
             
                  end
         | 
| 15 20 |  | 
| 21 | 
            +
                  # @param resource [Object]
         | 
| 22 | 
            +
                  # @param params [Hash]
         | 
| 23 | 
            +
                  # @param context [Hash]
         | 
| 24 | 
            +
                  # @return [Boolean]
         | 
| 16 25 | 
             
                  def included?(resource, params, context)
         | 
| 17 | 
            -
                    super | 
| 26 | 
            +
                    super && include_relation?(params)
         | 
| 18 27 | 
             
                  end
         | 
| 19 28 |  | 
| 29 | 
            +
                  # @param params [Hash]
         | 
| 30 | 
            +
                  # @return [Boolean]
         | 
| 20 31 | 
             
                  def include_relation?(params)
         | 
| 32 | 
            +
                    include?(params) && !exclude?(params)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  # @param params [Hash]
         | 
| 36 | 
            +
                  # @return [Boolean]
         | 
| 37 | 
            +
                  def exclude?(params)
         | 
| 38 | 
            +
                    return false if params[:exclude].nil?
         | 
| 39 | 
            +
                    return false if params[:exclude].empty?
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    params[:exclude_index].key?(key)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  # @param params [Hash]
         | 
| 45 | 
            +
                  # @return [Boolean]
         | 
| 46 | 
            +
                  def include?(params)
         | 
| 21 47 | 
             
                    return true if params[:include].nil?
         | 
| 48 | 
            +
                    return false if params[:include].empty?
         | 
| 22 49 |  | 
| 23 | 
            -
                    params[: | 
| 50 | 
            +
                    params[:include_index].key?(key)
         | 
| 24 51 | 
             
                  end
         | 
| 25 52 | 
             
                end
         | 
| 26 53 | 
             
              end
         | 
| @@ -3,91 +3,125 @@ | |
| 3 3 | 
             
            require 'forwardable'
         | 
| 4 4 |  | 
| 5 5 | 
             
            module FastSerializer
         | 
| 6 | 
            -
             | 
| 7 6 | 
             
              class Schema
         | 
| 8 | 
            -
                 | 
| 9 | 
            -
             | 
| 10 | 
            -
                def initialize(params = {})
         | 
| 11 | 
            -
                  @root | 
| 12 | 
            -
                  @ | 
| 13 | 
            -
                  @ | 
| 14 | 
            -
                  @params | 
| 15 | 
            -
             | 
| 16 | 
            -
                   | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
                   | 
| 7 | 
            +
                attr_reader :_root, :serialization_schema, :params, :strict
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize(params = {}, root = nil, strict = nil)
         | 
| 10 | 
            +
                  @root                   = root
         | 
| 11 | 
            +
                  @strict                 = strict || FastSerializer.config.strict
         | 
| 12 | 
            +
                  @serialization_schema   = FastSerializer::JsonModel::Object.new
         | 
| 13 | 
            +
                  @params                 = FastSerializer::Utils.symbolize_keys(params || {})
         | 
| 14 | 
            +
                  @params[:self]          = self
         | 
| 15 | 
            +
                  @params[:include_index] = {}
         | 
| 16 | 
            +
                  @params[:exclude_index] = {}
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  self.include = @params.delete(:include)
         | 
| 19 | 
            +
                  self.exclude = @params.delete(:exclude)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def include=(list)
         | 
| 23 | 
            +
                  return unless list
         | 
| 24 | 
            +
                  return if list.empty?
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  @params[:include]       = list.map(&:to_sym)
         | 
| 27 | 
            +
                  @params[:include_index] = @params[:include].map { |key| [key, nil] }.to_h
         | 
| 21 28 | 
             
                end
         | 
| 22 29 |  | 
| 23 | 
            -
                 | 
| 30 | 
            +
                def exclude=(list)
         | 
| 31 | 
            +
                  return unless list
         | 
| 32 | 
            +
                  return if list.empty?
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  @params[:exclude]       = list.map(&:to_sym)
         | 
| 35 | 
            +
                  @params[:exclude_index] = @params[:exclude].map { |key| [key, nil] }.to_h
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # Defines a list of attributes for serialization
         | 
| 39 | 
            +
                #
         | 
| 40 | 
            +
                # @param attribute_names [Array<String, Symbol>] a list of attributes to serialize
         | 
| 41 | 
            +
                # each of these attributes value is fetched calling a corresponding method from a resource instance
         | 
| 42 | 
            +
                # passed to the serializer
         | 
| 24 43 | 
             
                def attributes(*attribute_names)
         | 
| 25 44 | 
             
                  attribute_names.each do |attribute_name|
         | 
| 26 | 
            -
                    serialization_schema.add_attribute | 
| 27 | 
            -
                      key: | 
| 28 | 
            -
                      method: attribute_name
         | 
| 45 | 
            +
                    serialization_schema.add_attribute(
         | 
| 46 | 
            +
                      JsonModel::Attribute.new(key: attribute_name, method: attribute_name)
         | 
| 29 47 | 
             
                    )
         | 
| 30 48 | 
             
                  end
         | 
| 31 49 | 
             
                end
         | 
| 32 50 |  | 
| 33 | 
            -
                #  | 
| 34 | 
            -
                # | 
| 35 | 
            -
                # @param [ | 
| 51 | 
            +
                # Defines an attribute for serialization
         | 
| 52 | 
            +
                #
         | 
| 53 | 
            +
                # @param attribute_name [String, Symbol] an attribute name
         | 
| 54 | 
            +
                # @param opts [Hash] attribute options
         | 
| 55 | 
            +
                # @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
         | 
| 56 | 
            +
                # @option opts [Proc] :unless (see opts:if)
         | 
| 57 | 
            +
                # @param block [Proc] result is used as the attribute value
         | 
| 58 | 
            +
                #
         | 
| 36 59 | 
             
                def attribute(attribute_name, opts = {}, &block)
         | 
| 37 | 
            -
                  serialization_schema.add_attribute | 
| 38 | 
            -
                     | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 60 | 
            +
                  serialization_schema.add_attribute(
         | 
| 61 | 
            +
                    JsonModel::Attribute.new(
         | 
| 62 | 
            +
                      key: attribute_name,
         | 
| 63 | 
            +
                      method: block,
         | 
| 64 | 
            +
                      opts: opts
         | 
| 65 | 
            +
                    )
         | 
| 41 66 | 
             
                  )
         | 
| 42 67 | 
             
                end
         | 
| 43 68 |  | 
| 44 | 
            -
                #  | 
| 45 | 
            -
                # | 
| 69 | 
            +
                # Defines an attribute for serialization
         | 
| 70 | 
            +
                #
         | 
| 71 | 
            +
                # @param attribute_name [String, Symbol] an attribute name
         | 
| 72 | 
            +
                # @param opts [Hash] attribute options
         | 
| 73 | 
            +
                # @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
         | 
| 74 | 
            +
                # @option opts [Proc] :unless (see opts:if)
         | 
| 75 | 
            +
                # @option opts [FastSerializer::Schema::Mixin, nil] :serializer a serializer class with injected  module or a inherited class
         | 
| 76 | 
            +
                # @option opts [FastSerializer::Schema] :schema
         | 
| 77 | 
            +
                #
         | 
| 46 78 | 
             
                def has_one(attribute_name, opts = {})
         | 
| 47 79 | 
             
                  serialization_schema.add_attribute JsonModel::HasOneRelationship.new(
         | 
| 48 | 
            -
                    key: | 
| 49 | 
            -
                    method: | 
| 50 | 
            -
                    opts: | 
| 51 | 
            -
                    schema: | 
| 80 | 
            +
                    key: opts.delete(:key) || attribute_name,
         | 
| 81 | 
            +
                    method: opts.delete(:method) || attribute_name,
         | 
| 82 | 
            +
                    opts: opts,
         | 
| 83 | 
            +
                    schema: opts.delete(:schema),
         | 
| 52 84 | 
             
                    serializer: opts.delete(:serializer)
         | 
| 53 85 | 
             
                  )
         | 
| 54 86 | 
             
                end
         | 
| 55 87 |  | 
| 56 88 | 
             
                alias belongs_to has_one
         | 
| 57 89 |  | 
| 58 | 
            -
                # @param [String] | 
| 59 | 
            -
                # @param [Hash]  | 
| 90 | 
            +
                # @param attribute_name [String]
         | 
| 91 | 
            +
                # @param opts [Hash] attribute options
         | 
| 60 92 | 
             
                def has_many(attribute_name, opts = {})
         | 
| 61 | 
            -
                  serialization_schema.add_attribute | 
| 62 | 
            -
                     | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 93 | 
            +
                  serialization_schema.add_attribute(
         | 
| 94 | 
            +
                    JsonModel::HasManyRelationship.new(
         | 
| 95 | 
            +
                      key: opts.delete(:key) || attribute_name,
         | 
| 96 | 
            +
                      method: opts.delete(:method) || attribute_name,
         | 
| 97 | 
            +
                      opts: opts,
         | 
| 98 | 
            +
                      schema: opts.delete(:schema),
         | 
| 99 | 
            +
                      serializer: opts.delete(:serializer)
         | 
| 100 | 
            +
                    )
         | 
| 67 101 | 
             
                  )
         | 
| 68 102 | 
             
                end
         | 
| 69 103 |  | 
| 70 104 | 
             
                # @param [String] attribute_name
         | 
| 71 105 | 
             
                # @param [Hash] opts - attribute options
         | 
| 72 106 | 
             
                def list(attribute_name, opts = {})
         | 
| 73 | 
            -
                  serialization_schema.add_attribute | 
| 74 | 
            -
                     | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 107 | 
            +
                  serialization_schema.add_attribute(
         | 
| 108 | 
            +
                    JsonModel::Array.new(
         | 
| 109 | 
            +
                      key: attribute_name,
         | 
| 110 | 
            +
                      method: attribute_name,
         | 
| 111 | 
            +
                      opts: opts,
         | 
| 112 | 
            +
                      schema: opts.delete(:schema),
         | 
| 113 | 
            +
                      serializer: opts.delete(:serializer)
         | 
| 114 | 
            +
                    )
         | 
| 79 115 | 
             
                  )
         | 
| 80 116 | 
             
                end
         | 
| 81 117 |  | 
| 82 118 | 
             
                # @param [String] root_key - a key under which serialization result is nested
         | 
| 83 119 | 
             
                def root(root_key)
         | 
| 84 | 
            -
                   | 
| 120 | 
            +
                  @_root = root_key
         | 
| 85 121 | 
             
                end
         | 
| 86 122 |  | 
| 87 123 | 
             
                def deep_copy
         | 
| 88 | 
            -
                  schema | 
| 89 | 
            -
                  schema.params = params
         | 
| 90 | 
            -
                  schema._root  = _root
         | 
| 124 | 
            +
                  schema = FastSerializer::Schema.new(params, _root, strict)
         | 
| 91 125 |  | 
| 92 126 | 
             
                  serialization_schema.attributes.each do |key, attribute|
         | 
| 93 127 | 
             
                    schema.serialization_schema.attributes[key] = attribute
         | 
| @@ -97,20 +131,33 @@ module FastSerializer | |
| 97 131 | 
             
                end
         | 
| 98 132 |  | 
| 99 133 | 
             
                def serialize_resource(resource, params = {}, context = self)
         | 
| 100 | 
            -
                   | 
| 134 | 
            +
                  Utils.ref_merge(self.params, params)
         | 
| 135 | 
            +
                  _params_dup = FastSerializer::Utils.symbolize_keys(self.params)
         | 
| 101 136 | 
             
                  meta        = _params_dup.delete(:meta)
         | 
| 102 137 |  | 
| 103 | 
            -
                  is_collection =  | 
| 138 | 
            +
                  is_collection = if _params_dup.key?(:is_collection)
         | 
| 139 | 
            +
                    _params_dup.delete(:is_collection)
         | 
| 140 | 
            +
                    params.delete(:is_collection)
         | 
| 141 | 
            +
                  else
         | 
| 142 | 
            +
                    resource.respond_to?(:each) && !resource.respond_to?(:each_pair)
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  root = (_root || _params_dup.delete(:root))
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                  res = if is_collection
         | 
| 104 148 |  | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 149 | 
            +
                          if !context.is_a?(self.class)
         | 
| 150 | 
            +
                            # need to bind context
         | 
| 151 | 
            +
                            resource.map { |entry| context.class.new(entry, _params_dup).serializable_hash }
         | 
| 152 | 
            +
                          else
         | 
| 153 | 
            +
                            JsonModel::Array.new(schema: serialization_schema).serialize(resource, _params_dup, context)
         | 
| 154 | 
            +
                          end
         | 
| 110 155 |  | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 156 | 
            +
                        else
         | 
| 157 | 
            +
                          serialization_schema.serialize(resource, _params_dup, context)
         | 
| 158 | 
            +
                        end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  res = { root => res } if root && !root.empty?
         | 
| 114 161 |  | 
| 115 162 | 
             
                  res[:meta] = meta if res.is_a?(Hash) && meta
         | 
| 116 163 |  | 
| @@ -118,52 +165,7 @@ module FastSerializer | |
| 118 165 | 
             
                end
         | 
| 119 166 |  | 
| 120 167 | 
             
                def serialize_resource_to_json(resource, params = {}, context = self)
         | 
| 121 | 
            -
                  FastSerializer.config.coder.dump(serialize_resource(resource, params))
         | 
| 122 | 
            -
                end
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                module Mixin
         | 
| 125 | 
            -
             | 
| 126 | 
            -
                  module ClassMethods
         | 
| 127 | 
            -
                    attr_accessor :__schema__
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                    def inherited(subclass)
         | 
| 130 | 
            -
                      subclass.__schema__ = self.__schema__.deep_copy
         | 
| 131 | 
            -
                    end
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                    def method_missing(method, *args, &block)
         | 
| 134 | 
            -
                      if __schema__.respond_to?(method)
         | 
| 135 | 
            -
                        __schema__.public_send(method, *args, &block)
         | 
| 136 | 
            -
                      else
         | 
| 137 | 
            -
                        super
         | 
| 138 | 
            -
                      end
         | 
| 139 | 
            -
                    end
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  module InstanceMethods
         | 
| 143 | 
            -
                    attr_accessor :resource, :params
         | 
| 144 | 
            -
             | 
| 145 | 
            -
                    def initialize(resource, params = {})
         | 
| 146 | 
            -
                      self.resource = resource
         | 
| 147 | 
            -
                      self.params   = params || {}
         | 
| 148 | 
            -
                    end
         | 
| 149 | 
            -
             | 
| 150 | 
            -
                    def serializable_hash
         | 
| 151 | 
            -
                      self.class.__schema__.serialize_resource(resource, params, self)
         | 
| 152 | 
            -
                    end
         | 
| 153 | 
            -
             | 
| 154 | 
            -
                    def serialized_json
         | 
| 155 | 
            -
                      self.class.__schema__.serialize_resource_to_json(resource, params, self)
         | 
| 156 | 
            -
                    end
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                    alias as_json serializable_hash
         | 
| 159 | 
            -
                    alias to_json serialized_json
         | 
| 160 | 
            -
                  end
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                  def self.included(base)
         | 
| 163 | 
            -
                    base.extend ClassMethods
         | 
| 164 | 
            -
                    base.include InstanceMethods
         | 
| 165 | 
            -
                    base.__schema__ = FastSerializer::Schema.new
         | 
| 166 | 
            -
                  end
         | 
| 168 | 
            +
                  FastSerializer.config.coder.dump(serialize_resource(resource, params, context))
         | 
| 167 169 | 
             
                end
         | 
| 168 170 | 
             
              end
         | 
| 169 171 | 
             
            end
         |