Include 'linked' member for json-api collections

The options passed to the render are partitioned into adapter options
and serializer options. 'include' and 'root' are sent to the adapter,
not sure what options would go directly to serializer, but leaving this
in until I understand that better.
This commit is contained in:
Gary Gordon
2014-10-23 11:46:51 -04:00
parent 80ece39dd9
commit d5bae0c2f0
14 changed files with 250 additions and 56 deletions

View File

@@ -5,16 +5,19 @@ module ActiveModel
def initialize(serializer, options = {})
super
serializer.root = true
@hash = {}
@top = @options.fetch(:top) { @hash }
end
def serializable_hash(options = {})
@root = (options[:root] || serializer.json_key.to_s.pluralize).to_sym
@hash = {}
@root = (@options[:root] || serializer.json_key.to_s.pluralize).to_sym
if serializer.respond_to?(:each)
@hash[@root] = serializer.map{|s| self.class.new(s).serializable_hash[@root] }
@hash[@root] = serializer.map do |s|
self.class.new(s, @options.merge(top: @top)).serializable_hash[@root]
end
else
@hash[@root] = attributes_for_serializer(serializer, {})
@hash[@root] = attributes_for_serializer(serializer, @options)
serializer.each_association do |name, association, opts|
@hash[@root][:links] ||= {}
@@ -44,10 +47,10 @@ module ActiveModel
@hash[@root][:links][name][:ids] += serializers.map{|serializer| serializer.id.to_s }
end
unless options[:embed] == :ids || serializers.count == 0
@hash[:linked] ||= {}
@hash[:linked][name] ||= []
@hash[:linked][name] += serializers.map { |item| attributes_for_serializer(item, options) }
unless serializers.none? || @options[:embed] == :ids
serializers.each do |serializer|
add_linked(name, serializer)
end
end
end
@@ -62,17 +65,31 @@ module ActiveModel
@hash[@root][:links][name][:id] = serializer.id.to_s
end
unless options[:embed] == :ids
plural_name = name.to_s.pluralize.to_sym
@hash[:linked] ||= {}
@hash[:linked][plural_name] ||= []
@hash[:linked][plural_name].push attributes_for_serializer(serializer, options)
unless @options[:embed] == :ids
add_linked(name, serializer)
end
else
@hash[@root][:links][name] = nil
end
end
def add_linked(resource, serializer, parent = nil)
resource_path = [parent, resource].compact.join('.')
if include_assoc? resource_path
plural_name = resource.to_s.pluralize.to_sym
attrs = attributes_for_serializer(serializer, @options)
@top[:linked] ||= {}
@top[:linked][plural_name] ||= []
@top[:linked][plural_name].push attrs unless @top[:linked][plural_name].include? attrs
end
unless serializer.respond_to?(:each)
serializer.each_association do |name, association, opts|
add_linked(name, association, resource) if association
end
end
end
private
def attributes_for_serializer(serializer, options)
@@ -80,6 +97,10 @@ module ActiveModel
attributes[:id] = attributes[:id].to_s if attributes[:id]
attributes
end
def include_assoc? assoc
@options[:include] && @options[:include].split(',').include?(assoc.to_s)
end
end
end
end