lib/representable.rb in representable-1.8.5 vs lib/representable.rb in representable-2.0.0.rc1

- old
+ new

@@ -1,18 +1,29 @@ +require 'representable/inheritable' +require 'representable/config' require 'representable/definition' require 'representable/mapper' -require 'representable/config' +require 'representable/for_collection' +require 'representable/represent' +require 'representable/declarative' + +require 'uber/callable' +require 'representable/pipeline' + module Representable attr_writer :representable_attrs def self.included(base) base.class_eval do + extend Declarative extend ClassInclusions, ModuleExtensions extend ClassMethods - extend ClassMethods::Declarations - extend DSLAdditions + extend Feature + extend ForCollection + extend Represent + # register_feature Representable # Representable gets included automatically when creating inline representer. end end private # Reads values from +doc+ and sets properties accordingly. @@ -38,11 +49,11 @@ def cleanup_options(options) # TODO: remove me. this clearly belongs in Representable. options.reject { |k,v| [:include, :exclude].include?(k) } end def representable_attrs - @representable_attrs ||= self.class.representable_attrs # DISCUSS: copy, or better not? + @representable_attrs ||= self.class.representable_attrs # DISCUSS: copy, or better not? what about "freezing"? end def representable_mapper(format, options) bindings = representable_bindings_for(format, options) Mapper.new(bindings, represented, options) # TODO: remove self, or do we need it? and also represented! @@ -58,140 +69,52 @@ end module ClassInclusions def included(base) super - base.representable_attrs.inherit(representable_attrs) + base.inherit_module!(self) end def inherited(base) # DISCUSS: this could be in Decorator? but then we couldn't do B < A(include X) for non-decorators, right? super - base.representable_attrs.inherit(representable_attrs) + base.representable_attrs.inherit!(representable_attrs) # this should be inherit_class! end end module ModuleExtensions - # Copies the representable_attrs to the extended object. + # Copies the representable_attrs reference to the extended object. + # Note that changing attrs in the instance will affect the class configuration. def extended(object) super object.representable_attrs=(representable_attrs) # yes, we want a hard overwrite here and no inheritance. end end module ClassMethods - # Create and yield object and options. Called in .from_json and friends. - def create_represented(document, *args) - new.tap do |represented| - yield represented, *args if block_given? - end + # Gets overridden by Decorator as inheriting representers via include in Decorator means a bit more work (manifesting). + def inherit_module!(parent) + representable_attrs.inherit!(parent.representable_attrs) # Module just inherits. end def prepare(represented) - represented.extend(self) # was: PrepareStrategy::Extend. + represented.extend(self) end - - - module Declarations - def representable_attrs - @representable_attrs ||= build_config - end - - def representation_wrap=(name) - representable_attrs.wrap = name - end - - def property(name, options={}, &block) - representable_attrs << definition_class.new(name, options) - end - - def collection(name, options={}, &block) - options[:collection] = true # FIXME: don't override original. - property(name, options, &block) - end - - def hash(name=nil, options={}, &block) - return super() unless name # allow Object.hash. - - options[:hash] = true - property(name, options, &block) - end - - private - def definition_class - Definition - end - - def build_config - Config.new - end - end # Declarations end - # Internal module for DSL sugar that should not go into the core library. - module DSLAdditions - # Allows you to nest a block of properties in a separate section while still mapping them to the outer object. - def nested(name, options={}, &block) - options = options.merge( - :use_decorator => true, - :getter => lambda { |*| self }, - :setter => lambda { |*| }, - :instance => lambda { |*| self } - ) # DISCUSS: should this be a macro just as :parse_strategy? - property(name, options, &block) - end - - def property(name, options={}, &block) - modules = [] - - if options[:inherit] # TODO: move this to Definition. - parent = representable_attrs[name] - modules << parent[:extend].evaluate(nil) if parent[:extend]# we can savely assume this is _not_ a lambda. # DISCUSS: leave that in #representer_module? - end # FIXME: can we handle this in super/Definition.new ? - - if block_given? - handle_deprecated_inline_extend!(modules, options) - - options[:extend] = inline_representer_for(modules, name, options, &block) + module Feature + def feature(*mods) + mods.each do |mod| + include mod + register_feature(mod) end - - return parent.merge!(options) if options.delete(:inherit) - - super end - def inline_representer(base_module, name, options, &block) # DISCUSS: separate module? - Module.new do - include *base_module # Representable::JSON or similar. - instance_exec &block - end - end - private - def inline_representer_for(modules, name, options, &block) - representer = options[:use_decorator] ? Decorator : self - modules = [representer_engine] + modules - - representer.inline_representer(modules.compact.reverse, name, options, &block) + def register_feature(mod) + representable_attrs[:features][mod] = true end - - def handle_deprecated_inline_extend!(modules, options) # TODO: remove in 2.0. - return unless include_module = options.delete(:extend) and not options[:inherit] - - warn "[Representable] Using :extend with an inline representer is deprecated. Include the module in the inline block." - modules << include_module - end - end # DSLAdditions -end - - -module Representable - autoload :Hash, 'representable/hash' - - module Hash - autoload :AllowSymbols, 'representable/hash/allow_symbols' - autoload :Collection, 'representable/hash/collection' end - - autoload :Decorator, 'representable/decorator' end + +require 'representable/autoload' \ No newline at end of file