lib/praxis-blueprints/field_expander.rb in praxis-blueprints-3.0 vs lib/praxis-blueprints/field_expander.rb in praxis-blueprints-3.1
- old
+ new
@@ -1,15 +1,7 @@
module Praxis
class FieldExpander
- class CircularExpansionError < StandardError
- attr_reader :stack
- def initialize(message, stack=[])
- super(message)
- @stack = stack
- end
- end
-
def self.expand(object, fields=true)
self.new.expand(object,fields)
end
attr_reader :stack
@@ -24,25 +16,30 @@
end
end
def expand(object, fields=true)
if stack[object].include? fields
- raise CircularExpansionError, "Circular expansion detected for object #{object.inspect} with fields #{fields.inspect}"
+ if history[object].include? fields
+ return history[object][fields]
+ end
+ # We should probably never get here, since we should have a record
+ # of the history of an expansion if we're trying to redo it,
+ # but we should also be conservative and raise here just in case.
+ raise "Circular expansion detected for object #{object.inspect} with fields #{fields.inspect}"
else
stack[object] << fields
end
- if object.kind_of?(Praxis::View)
+ result = if object.kind_of?(Praxis::View)
self.expand_view(object, fields)
elsif object.kind_of? Attributor::Attribute
self.expand_type(object.type, fields)
else
self.expand_type(object,fields)
end
- rescue CircularExpansionError => e
- e.stack.unshift [object,fields]
- raise
+
+ result
ensure
stack[object].delete fields
end
def expand_fields(attributes, fields)
@@ -65,24 +62,43 @@
end
end
def expand_view(object,fields=true)
+ history[object][fields] = if object.kind_of?(Praxis::CollectionView)
+ []
+ else
+ {}
+ end
+
result = expand_fields(object.contents, fields) do |dumpable, sub_fields|
self.expand(dumpable, sub_fields)
end
- return [result] if object.kind_of?(Praxis::CollectionView)
- result
+ if object.kind_of?(Praxis::CollectionView)
+ history[object][fields] << result
+ else
+ history[object][fields].merge!(result)
+ end
+ history[object][fields]
end
def expand_type(object,fields=true)
unless object.respond_to?(:attributes)
if object.respond_to?(:member_attribute)
- fields = fields[0] if fields.kind_of? Array
- return [self.expand(object.member_attribute.type, fields)]
+ if history[object].include? fields
+ return history[object][fields]
+ end
+ history[object][fields] = []
+
+ new_fields = fields.kind_of?(Array) ? fields[0] : fields
+
+ result = [self.expand(object.member_attribute.type, new_fields)]
+ history[object][fields].push(*result)
+
+ return result
else
return true
end
end
@@ -93,12 +109,14 @@
if history[object].include? fields
return history[object][fields]
end
- history[object][fields] = expand_fields(object.attributes, fields) do |dumpable, sub_fields|
+ history[object][fields] = {}
+ result = expand_fields(object.attributes, fields) do |dumpable, sub_fields|
self.expand(dumpable.type, sub_fields)
end
+ history[object][fields].merge!(result)
end
end
end