lib/representable/definition.rb in representable-1.7.7 vs lib/representable/definition.rb in representable-1.8.0

- old
+ new

@@ -1,82 +1,114 @@ +require 'uber/options' +require "representable/parse_strategies" + module Representable # Created at class compile time. Keeps configuration options for one property. - class Definition - attr_reader :name, :options + class Definition < Hash + attr_reader :name alias_method :getter, :name def initialize(sym, options={}) - @name = sym.to_s - @options = options + super() + options = options.clone + + handle_deprecations!(options) + + @name = sym.to_s + # defaults: + options[:as] ||= @name + + setup!(options) end - def clone - self.class.new(name, options.clone) # DISCUSS: make generic Definition.cloned_attribute that passes list to constructor. + # TODO: test merge!. + def merge!(options) + setup!(options) + self end + private :default, :[]= + + def options # TODO: remove in 2.0. + warn "Representable::Definition#option is deprecated, use #[] directly." + self + end + def setter :"#{name}=" end def typed? - deserialize_class.is_a?(Class) or representer_module or options[:instance] # also true if only :extend is set, for people who want solely rendering. + self[:class] or self[:extend] or self[:instance] end + def representable? + return if self[:representable] === false + self[:representable] or typed? + end + def array? - options[:collection] + self[:collection] end def hash? - options[:hash] + self[:hash] end - def deserialize_class - options[:class] - end - - def from - # TODO: deprecate :from. - (options[:from] || options[:as] || name).to_s - end - def default_for(value) - return default if skipable_nil_value?(value) + return self[:default] if skipable_nil_value?(value) value end def has_default? - options.has_key?(:default) + has_key?(:default) end def representer_module - options[:extend] or options[:decorator] + self[:extend] end - def attribute - options[:attribute] + def skipable_nil_value?(value) + value.nil? and not self[:render_nil] end - def content - options[:content] + def create_binding(*args) + self[:binding].call(self, *args) end - def skipable_nil_value?(value) - value.nil? and not options[:render_nil] + private + def setup!(options) + handle_extend!(options) + handle_as!(options) + + # DISCUSS: we could call more macros here (e.g. for :nested). + Representable::ParseStrategy.apply!(options) + + for name, value in options + value = Uber::Options::Value.new(value) if dynamic_options.include?(name) + self[name] = value + end end - def default - options[:default] + def dynamic_options + [:as, :getter, :setter, :class, :instance, :reader, :writer, :extend, :prepare, :if] end - def binding - options[:binding] + def handle_extend!(options) + mod = options.delete(:extend) || options.delete(:decorator) and options[:extend] = mod end - def create_binding(*args) - binding.call(self, *args) + def handle_as!(options) + options[:as] = options[:as].to_s if options[:as].is_a?(Symbol) # Allow symbols for as: end - def sync? - options[:parse_strategy] == :sync + # TODO: remove in 2.0. + def handle_deprecations!(options) + raise "The :from option got replaced by :as in Representable 1.8!" if options[:from] + + if options[:decorator_scope] + warn "[Representable] Deprecation: `decorator_scope: true` is deprecated, use `exec_context: :decorator` instead." + options.merge!(:exec_context => :decorator) + end end end end