lib/jsonapionify/api/resource/builders.rb in jsonapionify-0.9.0 vs lib/jsonapionify/api/resource/builders.rb in jsonapionify-0.9.1

- old
+ new

@@ -1,53 +1,100 @@ module JSONAPIonify::Api module Resource::Builders extend ActiveSupport::Concern + FALSEY_STRINGS = JSONAPIonify::FALSEY_STRINGS + TRUTHY_STRINGS = JSONAPIonify::TRUTHY_STRINGS + Structure = JSONAPIonify::Structure module ClassMethods - def build_resource(request, instance, fields: api.fields, relationships: true, links: true) - relationships = false if JSONAPIonify::FALSEY_STRINGS.include? request.params['include-relationships'] + + def build_resource( + context, + instance, + fields:, + relationships: true, + links: true, + include_cursor: false, &block + ) + example_id = generate_id + include_rel_param = context.params['include-relationships'] + relationships = false if FALSEY_STRINGS.include?(include_rel_param) return nil unless instance - resource_url = build_url(request, instance) + resource_url = build_url(context, instance) id = build_id(instance) - JSONAPIonify::Structure::Objects::Resource.new.tap do |resource| + Structure::Objects::Resource.new.tap do |resource| resource[:id] = id resource[:type] = type - resource[:attributes] = fields[type.to_sym].each_with_object(JSONAPIonify::Structure::Objects::Attributes.new) do |member, attributes| - attributes[member.to_sym] = instance.public_send(member) + resource[:attributes] = fields[type.to_sym].each_with_object( + Structure::Objects::Attributes.new + ) do |member, attributes| + attribute = self.attributes.find { |a| a.name == member.to_sym } + unless attribute.supports_read_for_action?(context.action_name, context) + error_block = + context.resource.class.error_definitions[:internal_server_error] + context.errors.evaluate( + name, + error_block: error_block, + runtime_block: proc {} + ) + end + attributes[member.to_sym] = attribute.resolve( + instance, context, example_id: example_id + ) end - resource[:links] = JSONAPIonify::Structure::Objects::Links.new( + resource[:links] = Structure::Objects::Links.new( self: resource_url ) if links resource[:meta] = { - cursor: build_cursor_from_instance(request, instance) - } + cursor: build_cursor_from_instance(context, instance) + } if include_cursor - resource[:relationships] = relationship_definitions.each_with_object(JSONAPIonify::Structure::Maps::Relationships.new) do |rel, hash| - hash[rel.name] = build_relationship(request, instance, rel.name) - end if relationships + resource[:relationships] = relationship_definitions.each_with_object( + Structure::Maps::Relationships.new + ) do |rel, hash| + hash[rel.name] = build_relationship(context, instance, rel.name) + end if relationships || context.includes.present? + + block.call(resource, instance) if block end end def build_resource_identifier(instance) - JSONAPIonify::Structure::Objects::ResourceIdentifier.new( + Structure::Objects::ResourceIdentifier.new( id: build_id(instance), type: type.to_s ) end - def build_collection(request, collection, fields: api.fields) - relationships = JSONAPIonify::TRUTHY_STRINGS.include? request.params['include-relationships'] - collection.each_with_object(JSONAPIonify::Structure::Collections::Resources.new) do |instance, resources| - resources << build_resource(request, instance, fields: fields, relationships: relationships) + def build_collection( + context, + collection, + fields:, + include_cursors: false, + &block + ) + include_rel_param = context.params['include-relationships'] + relationships = TRUTHY_STRINGS.include? include_rel_param + collection.each_with_object( + Structure::Collections::Resources.new + ) do |instance, resources| + resources << build_resource( + context, + instance, + fields: fields, + relationships: relationships, + include_cursor: include_cursors, + &block + ) end end - def build_cursor_from_instance(request, instance) - sort_string = request.params['sort'] + def build_cursor_from_instance(context, instance) + sort_string = context.params['sort'] sort_fields = sort_fields_from_sort_string(sort_string) attrs_with_values = sort_fields.each_with_object({}) do |field, hash| hash[field.name] = instance.send(field.name) end Base64.urlsafe_encode64(JSON.dump( @@ -58,53 +105,57 @@ } )) end def build_identifier_collection(collection) - collection.each_with_object(JSONAPIonify::Structure::Collections::ResourceIdentifiers.new) do |instance, resource_identifiers| + collection.each_with_object( + JSONAPIonify::Structure::Collections::ResourceIdentifiers.new + ) do |instance, resource_identifiers| resource_identifiers << build_resource_identifier(instance) end end - def build_relationship(request, instance, name, links: true, data: false) - resource_url = build_url(request, instance) + def build_relationship(context, instance, name, links: true, data: false) + resource_url = build_url(context, instance) relationship = self.relationship(name) JSONAPIonify::Structure::Objects::Relationship.new.tap do |rel| rel[:links] = relationship.build_links(resource_url) if links - if data + if data || context.includes.present? rel[:data] = - if relationship < Resource::RelationshipToMany + if relationship.rel.is_a? Relationship::Many instance.send(name).map do |child| relationship.build_resource_identifier(child) end - elsif relationship < Resource::RelationshipToOne + elsif relationship.rel.is_a? Relationship::One value = instance.send(name) relationship.build_resource_identifier value if value end end end end - def build_url(request, instance = nil) - URI.parse(request.root_url).tap do |uri| + def build_url(context, instance = nil) + URI.parse(context.request.root_url).tap do |uri| uri.path = if instance File.join(uri.path, type, build_id(instance)) else - File.join(request.root_url, type) + File.join(context.request.root_url, type) end - sticky_params = self.sticky_params(request.params) + sticky_params = self.sticky_params(context.params) uri.query = sticky_params.to_param if sticky_params.present? end.to_s end def build_id(instance) instance.send(id_attribute).to_s end end included do - delegate *(ClassMethods.instance_methods - JSONAPIonify::Api::Resource::Builders.instance_methods), to: :class + delegated_methods = ClassMethods.instance_methods - + JSONAPIonify::Api::Resource::Builders.instance_methods + delegate(*delegated_methods, to: :class) end end end