lib/representable.rb in representable-0.11.0 vs lib/representable.rb in representable-0.12.0
- old
+ new
@@ -1,10 +1,11 @@
require 'representable/definition'
module Representable
def self.included(base)
base.class_eval do
+ extend ClassMethods
extend ClassMethods::Declarations
extend ClassMethods::Accessors
def self.included(base)
base.representable_attrs.push(*representable_attrs) # "inherit".
@@ -19,37 +20,37 @@
end
end
end
# Reads values from +doc+ and sets properties accordingly.
- def update_properties_from(doc, &block)
+ def update_properties_from(doc, options, &block)
representable_bindings.each do |bin|
- next if eval_property_block(bin, &block) # skip if block is false.
+ next if skip_property?(bin, options)
value = bin.read(doc) || bin.definition.default
send(bin.definition.setter, value)
end
self
end
private
# Compiles the document going through all properties.
- def create_representation_with(doc, &block)
+ def create_representation_with(doc, options, &block)
representable_bindings.each do |bin|
- next if eval_property_block(bin, &block) # skip if block is false.
+ next if skip_property?(bin, options)
value = send(bin.definition.getter) || bin.definition.default # DISCUSS: eventually move back to Ref.
bin.write(doc, value) if value
end
doc
end
- # Returns true unless a eventually given block returns false. Yields the symbolized
- # property name.
- def eval_property_block(binding)
- # TODO: no magic symbol conversion!
- block_given? and not yield binding.definition.name.to_sym
+ # Checks and returns if the property should be included.
+ def skip_property?(binding, options)
+ return unless props = options[:except] || options[:include]
+ res = props.include?(binding.definition.name.to_sym)
+ options[:include] ? !res : res
end
def representable_attrs
@representable_attrs ||= self.class.representable_attrs # DISCUSS: copy, or better not?
end
@@ -63,51 +64,59 @@
representable_attrs.wrap_for(self.class.name)
end
module ClassMethods # :nodoc:
+ # 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
+ end
+
module Declarations
def definition_class
Definition
end
# Declares a represented document node, which is usually a XML tag or a JSON key.
#
# Examples:
#
- # representable_property :name
- # representable_property :name, :from => :title
- # representable_property :name, :as => Name
- # representable_property :name, :accessors => false
- # representable_property :name, :default => "Mike"
- def representable_property(name, options={})
- attr = add_representable_property(name, options)
+ # property :name
+ # property :name, :from => :title
+ # property :name, :class => Name
+ # property :name, :accessors => false
+ # property :name, :default => "Mike"
+ def property(name, options={})
+ attr = add_property(name, options)
attr_reader(attr.getter) unless options[:accessors] == false
attr_writer(attr.getter) unless options[:accessors] == false
end
# Declares a represented document node collection.
#
# Examples:
#
- # representable_collection :products
- # representable_collection :products, :from => :item
- # representable_collection :products, :as => Product
- def representable_collection(name, options={})
+ # collection :products
+ # collection :products, :from => :item
+ # collection :products, :class => Product
+ def collection(name, options={})
options[:collection] = true
- representable_property(name, options)
+ property(name, options)
end
private
- def add_representable_property(*args)
+ def add_property(*args)
definition_class.new(*args).tap do |attr|
representable_attrs << attr
end
end
end
-
+
+
module Accessors
def representable_attrs
@representable_attrs ||= Config.new
end
@@ -115,10 +124,11 @@
representable_attrs.wrap = name
end
end
end
+
class Config < Array
attr_accessor :wrap
# Computes the wrap string or returns false.
def wrap_for(name)
@@ -131,8 +141,21 @@
def infer_name_for(name)
name.to_s.split('::').last.
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
downcase
+ end
+ end
+
+
+ # Allows mapping formats to representer classes.
+ # DISCUSS: this module might be removed soon.
+ module Represents
+ def represents(format, options)
+ representer[format] = options[:with]
+ end
+
+ def representer
+ @represents_map ||= {}
end
end
end