lib/representable/binding.rb in representable-3.0.4 vs lib/representable/binding.rb in representable-3.1.0

- old
+ new

@@ -1,10 +1,28 @@ +# frozen_string_literal: true + +require 'uber/delegates' + module Representable # The Binding provides methods to read/write the fragment for one property. # # Actually parsing the fragment from the document happens in Binding#read, everything after that is generic. class Binding + class Map < Array + def call(method, options) + each do |bin| + options[:binding] = bin # this is so much faster than options.merge(). + bin.send(method, options) + end + end + + # TODO: Merge with Definitions. + def <<(binding) # can be slow. this is compile time code. + (existing = find { |bin| bin.name == binding.name }) ? self[index(existing)] = binding : super(binding) + end + end + class FragmentNotFound end def self.build(definition) build_for(definition) @@ -27,57 +45,58 @@ # and #uncompile_fragment in Mapper. module Deprecatable # Retrieve value and write fragment to the doc. def compile_fragment(options) - render_pipeline(nil, options).(nil, options) + render_pipeline(nil, options).call(nil, options) end # Parse value from doc and update the model property. def uncompile_fragment(options) - parse_pipeline(options[:doc], options).(options[:doc], options) + parse_pipeline(options[:doc], options).call(options[:doc], options) end end include Deprecatable module EvaluateOption def evaluate_option(name, input, options) proc = self[name] # puts "@@@@@ #{self.inspect}, #{name}...... #{self[name]}" - proc.(send(:exec_context, options), options.merge(user_options: options[:options][:user_options], input: input)) # from Uber::Options::Value. # NOTE: this can also be the Proc object if it's not wrapped by Uber:::Value. + proc.call(exec_context: send(:exec_context, options), keyword_arguments: options.merge(user_options: options[:options][:user_options], input: input)) # from Uber::Options::Value. # NOTE: this can also be the Proc object if it's not wrapped by Uber:::Value. end end include EvaluateOption def [](name) @definition[name] end def skipable_empty_value?(value) - value.nil? and not self[:render_nil] + value.nil? and !(self[:render_nil]) end def default_for(value) return self[:default] if skipable_empty_value?(value) + value end attr_accessor :cached_representer - require "representable/pipeline_factories" + require 'representable/pipeline_factories' include Factories - private + private def setup_exec_context! - @exec_context = ->(options) { options[:represented] } unless self[:exec_context] - @exec_context = ->(options) { self } if self[:exec_context] == :binding - @exec_context = ->(options) { options[:decorator] } if self[:exec_context] == :decorator + @exec_context = ->(options) { options[:represented] } unless self[:exec_context] + @exec_context = ->(_options) { self } if self[:exec_context] == :binding + @exec_context = ->(options) { options[:decorator] } if self[:exec_context] == :decorator end def exec_context(options) - @exec_context.(options) + @exec_context.call(options) end def parse_pipeline(input, options) @parse_pipeline ||= pipeline_for(:parse_pipeline, input, options) { Pipeline[*parse_functions] } end @@ -88,11 +107,12 @@ # generics for collection bindings. module Collection def skipable_empty_value?(value) # TODO: this can be optimized, again. - return true if value.nil? and not self[:render_nil] # FIXME: test this without the "and" - return true if self[:render_empty] == false and value and value.size == 0 # TODO: change in 2.0, don't render emtpy. + return true if value.nil? && !(self[:render_nil]) # FIXME: test this without the "and" + + true if (self[:render_empty] == false) && value && value.empty? # TODO: change in 2.0, don't render emtpy. end end end class DeserializeError < RuntimeError