lib/representable/definition.rb in representable-1.8.5 vs lib/representable/definition.rb in representable-2.0.0.rc1
- old
+ new
@@ -1,38 +1,45 @@
require 'uber/options'
require "representable/parse_strategies"
module Representable
# Created at class compile time. Keeps configuration options for one property.
- class Definition < Hash
+ class Definition
+ include Representable::Cloneable
+
attr_reader :name
alias_method :getter, :name
- def initialize(sym, options={})
- super()
- options = options.clone
+ def initialize(sym, options={}, &block)
+ @options = {}
+ # @options = Inheritable::Hash.new # allows deep cloning. we then had to set Pipeline cloneable.
+ @name = sym.to_s
+ options = options.clone
- handle_deprecations!(options)
-
- @name = sym.to_s
# defaults:
- options[:as] ||= @name
+ options[:parse_filter] = Pipeline[*options[:parse_filter]]
+ options[:render_filter] = Pipeline[*options[:render_filter]]
+ options[:as] ||= @name
- setup!(options)
+ setup!(options, &block)
end
- # TODO: test merge!.
- def merge!(options)
- setup!(options)
+ def merge!(options, &block)
+ options = options.clone
+
+ options[:parse_filter] = @options[:parse_filter].push(*options[:parse_filter])
+ options[:render_filter] = @options[:render_filter].push(*options[:render_filter])
+
+ setup!(options, &block) # FIXME: this doesn't yield :as etc.
self
end
- private :[]= # TODO: re-privatize #default when this is sorted with Rubinius.
+ extend Forwardable
+ def_delegators :@runtime_options, :[], :each
- def options # TODO: remove in 2.0.
- warn "Representable::Definition#option is deprecated, use #[] directly."
- self
+ def clone
+ self.class.new(name, @options.clone)
end
def setter
:"#{name}="
end
@@ -53,64 +60,64 @@
def hash?
self[:hash]
end
def default_for(value)
- return self[:default] if skipable_nil_value?(value)
+ return self[:default] if skipable_empty_value?(value)
value
end
def has_default?
- has_key?(:default)
+ @options.has_key?(:default)
end
def representer_module
- self[:extend]
+ @options[:extend]
end
def skipable_empty_value?(value)
return true if array? and self[:render_empty] == false and value and value.size == 0 # TODO: change in 2.0, don't render emtpy.
value.nil? and not self[:render_nil]
end
- alias_method :skipable_nil_value?, :skipable_empty_value? # TODO: remove in 1.9 .
def create_binding(*args)
self[:binding].call(self, *args)
end
private
- def setup!(options)
+ def setup!(options, &block)
handle_extend!(options)
handle_as!(options)
# DISCUSS: we could call more macros here (e.g. for :nested).
Representable::ParseStrategy.apply!(options)
+ yield options if block_given?
+ @options.merge!(options)
+
+ runtime_options!(@options)
+ end
+
+ # wrapping dynamic options in Value does save runtime, as this is used very frequently (and totally unnecessary to wrap an option
+ # at runtime, its value never changes).
+ def runtime_options!(options)
+ @runtime_options = {}
+
for name, value in options
value = Uber::Options::Value.new(value) if dynamic_options.include?(name)
- self[name] = value
+ @runtime_options[name] = value
end
end
def dynamic_options
- [:as, :getter, :setter, :class, :instance, :reader, :writer, :extend, :prepare, :if, :deserialize, :serialize]
+ [:as, :getter, :setter, :class, :instance, :reader, :writer, :extend, :prepare, :if, :deserialize, :serialize, :render_filter, :parse_filter]
end
def handle_extend!(options)
mod = options.delete(:extend) || options.delete(:decorator) and options[:extend] = mod
end
def handle_as!(options)
options[:as] = options[:as].to_s if options[:as].is_a?(Symbol) # Allow symbols for as:
- end
-
- # 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