From 92d88a91125e15d32d1547f0e6ba0aad41ee65ac Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Wed, 28 Jun 2017 22:13:47 -0500 Subject: [PATCH] 100% documented --- lib/ams/serializer.rb | 127 +++++++++++++++++++++++++++++++++++++++++- lib/ams/version.rb | 3 + 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/lib/ams/serializer.rb b/lib/ams/serializer.rb index dd918847..65c788a5 100644 --- a/lib/ams/serializer.rb +++ b/lib/ams/serializer.rb @@ -13,7 +13,7 @@ module AMS # models, as in {http://jsonapi.org/format/#document-resource-object-fields # JSON:API resource object fields} # - # @example: + # @example # # class ApplicationSerializer < AMS::Serializer; end # class UserModelSerializer < ApplicationSerializer @@ -38,16 +38,22 @@ module AMS class << self attr_accessor :_attributes, :_relations, :_id_field, :_type + # @api private + # Macro to add an instance method to the receiver def add_instance_method(body, receiver = self) cl = caller_locations[0] silence_warnings { receiver.module_eval body, cl.absolute_path, cl.lineno } end + # @api private + # Macro to add a class method to the receiver def add_class_method(body, receiver) cl = caller_locations[0] silence_warnings { receiver.class_eval body, cl.absolute_path, cl.lineno } end + # @api private + # Silence warnings, primarily when redefining methods def silence_warnings original_verbose = $VERBOSE $VERBOSE = nil @@ -65,10 +71,20 @@ module AMS add_instance_method "def id; object.id; end", base end + # Configure resource type + # Inferred from serializer name by default + # + # @example + # type :users def type(type) self._type = type end + # Configures the field on the object which uniquely identifies it. + # By default, id `object.id` + # + # @example + # id_field :user_id def id_field(id_field) self._id_field = id_field add_instance_method <<-METHOD @@ -78,6 +94,15 @@ module AMS METHOD end + # @example + # attribute :color, key: :hue + # + # 1. Generates the method + # def color + # object.color + # end + # 2. Stores the attribute :color + # with options key: :hue def attribute(attribute_name, key: attribute_name) fail "ForbiddenKey" if attribute_name == :id _attributes[attribute_name] = { key: key } @@ -88,6 +113,14 @@ module AMS METHOD end + # 1. Generates the methods + # 2. Stores the relationship :articles with the given options + # + # @example + # relation :articles, type: :articles, to: :many, key: :posts + # relation :articles, type: :articles, to: :many, key: :posts, ids: "object.article_ids" + # relation :article, type: :articles, to: :one, key: :post + # relation :article, type: :articles, to: :one, key: :post, id: "object.article_id" def relation(relation_name, type:, to:, key: relation_name, **options) _relations[relation_name] = { key: key, type: type, to: to } case to @@ -98,6 +131,27 @@ module AMS end end + # @example + # relation :articles, type: :articles, to: :many, key: :posts + # + # def related_articles_ids + # object.aritcles.pluck(:id) + # end + # + # def articles + # relationship_object(related_articles_ids, :articles) + # end + # + # @example + # relation :articles, type: :articles, to: :many, key: :posts, ids: "object.article_ids" + # + # def related_articles_ids + # object.article_ids + # end + # + # def articles + # relationship_object(related_articles_ids, :articles) + # end def _relation_to_many(relation_name, type:, key: relation_name, **options) ids_method = options.fetch(:ids) do "object.#{relation_name}.pluck(:id)" @@ -113,6 +167,27 @@ module AMS METHOD end + # @example + # relation :article, type: :articles, to: :one, key: :post + # + # def related_article_id + # object.article.id + # end + # + # def article + # relationship_object(related_article_id, :articles) + # end + # + # @example + # relation :article, type: :articles, to: :one, key: :post, id: "object.article_id" + # + # def related_article_id + # object.article_id + # end + # + # def article + # relationship_object(related_article_id, :articles) + # end def _relation_to_one(relation_name, type:, key: relation_name, **options) id_method = options.fetch(:id) do "object.#{relation_name}.id" @@ -134,11 +209,13 @@ module AMS attr_reader :object - # @param model [Object] the model whose data is used in serialization + # @param object [Object] the model whose data is used in serialization def initialize(object) @object = object end + # Builds a Hash representation of the object + # using id, type, attributes, relationships def to_h { id: id, @@ -150,10 +227,26 @@ module AMS end alias as_json to_h + # Builds a JSON representation from as_json def to_json dump(as_json) end + # Builds a Hash of specified attributes + # + # 1. For each configured attribute + # 2. map its :key to the attribute + # + # @example + # For the configured attribute: + # + # attribute :color, key: :hue + # + # The attributes hash will include: + # + # attributes[:hue] = send(:color) + # + # TODO: Support sparse fieldsets def attributes fields = {} _attributes.each do |attribute_name, config| @@ -162,6 +255,21 @@ module AMS fields end + # Builds a Hash of specified relations + # + # 1. For each configured relation + # 2. map its :key to the relationship + # + # @example + # For the configured relation: + # + # relation :user, key: :author + # + # The relationships hash will include: + # + # relations[:author] = send(:user) + # + # TODO: Support sparse fieldsets def relations fields = {} _relations.each do |relation_name, config| @@ -170,18 +278,29 @@ module AMS fields end + # The configured type def type self.class._type end + # The configured attributes def _attributes self.class._attributes end + # The configured relations def _relations self.class._relations end + # Builds a relationship object + # + # @example + # relationship_object(1, :users) + # #=> { data: { id: 1, type: :users} } + # + # relationship_object([1,2], :users) + # #=> { data: [ { id: 1, type: :users}, { id: 2, type: :users] } } def relationship_object(id_or_ids, type) data = if id_or_ids.respond_to?(:to_ary) @@ -197,10 +316,14 @@ module AMS { "id": id, "type": type } end + # Dumps obj to JSON + # @param obj [Hash,Array,String,nil,Number] + # @return [String] JSON def dump(obj) JSON.dump(obj) end + # @!visibility private def send(*args) __send__(*args) end diff --git a/lib/ams/version.rb b/lib/ams/version.rb index 324aa258..41b776d5 100644 --- a/lib/ams/version.rb +++ b/lib/ams/version.rb @@ -1,4 +1,7 @@ # frozen_string_literal: true +# +# :nodoc: module AMS + # :nodoc: VERSION = "0.99.0" end