jei 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/jei.rb CHANGED
@@ -1,14 +1,7 @@
1
1
  require 'json'
2
2
  require 'set'
3
3
 
4
- require 'jei/builders/attributes_node_builder'
5
- require 'jei/builders/data_node_builder'
6
- require 'jei/builders/document_builder'
7
- require 'jei/builders/included_node_builder'
8
- require 'jei/builders/links_node_builder'
9
- require 'jei/builders/relationship_node_builder'
10
- require 'jei/builders/relationships_node_builder'
11
- require 'jei/builders/resource_node_builder'
4
+ require 'jei/error'
12
5
 
13
6
  require 'jei/nodes/node'
14
7
 
@@ -28,14 +21,23 @@ require 'jei/nodes/resource_node'
28
21
  require 'jei/nodes/data_node'
29
22
  require 'jei/nodes/collection_data_node'
30
23
 
31
- require 'jei/attribute'
24
+ require 'jei/builders/attributes_node_builder'
25
+ require 'jei/builders/data_node_builder'
26
+ require 'jei/builders/document_builder'
27
+ require 'jei/builders/included_node_builder'
28
+ require 'jei/builders/links_node_builder'
29
+ require 'jei/builders/relationship_node_builder'
30
+ require 'jei/builders/relationships_node_builder'
31
+ require 'jei/builders/resource_node_builder'
32
+
32
33
  require 'jei/document'
34
+ require 'jei/fieldset'
33
35
  require 'jei/link'
34
36
  require 'jei/path'
35
- require 'jei/relationship'
36
37
  require 'jei/serializer'
37
38
 
38
- require 'jei/version'
39
+ require 'jei/field'
40
+ require 'jei/attribute'
41
+ require 'jei/relationship'
39
42
 
40
- module Jei
41
- end
43
+ require 'jei/version'
data/lib/jei/attribute.rb CHANGED
@@ -1,22 +1,4 @@
1
1
  module Jei
2
- class Attribute
3
- # @return [Symbol]
4
- attr_reader :name
5
-
6
- # @param [Symbol] name
7
- # @param [Proc, Symbol] value
8
- def initialize(name, value = name)
9
- @name = name
10
- @value = value
11
- end
12
-
13
- # @param [Serializer] serializer
14
- def evaluate(serializer)
15
- if @value.is_a?(Proc)
16
- serializer.instance_eval(&@value)
17
- else
18
- serializer.resource.send(@value)
19
- end
20
- end
2
+ class Attribute < Field
21
3
  end
22
4
  end
@@ -1,12 +1,14 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module AttributesNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Serializer] serializer
5
7
  # @return [AttributesNode]
6
- def self.build(serializer)
8
+ def self.build(attributes, serializer)
7
9
  node = AttributesNode.new
8
10
 
9
- serializer.attributes.values.each do |attribute|
11
+ attributes.each do |attribute|
10
12
  node.children << AttributeNode.new(serializer, attribute)
11
13
  end
12
14
 
@@ -1,6 +1,8 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module DataNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Serializer] serializer
5
7
  # @return [DataNode]
6
8
  def self.build(serializer)
@@ -1,6 +1,8 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module DocumentBuilder
4
+ include Nodes
5
+
4
6
  # @param [Object] resource
5
7
  # @param [Hash<Symbol, Object>] options
6
8
  # @return [Document]
@@ -17,57 +19,48 @@ module Jei
17
19
  return document
18
20
  end
19
21
 
22
+ fieldsets = options[:fields] ? Fieldset.parse(options[:fields]) : {}
23
+
20
24
  if resource.is_a?(Enumerable)
21
25
  node = CollectionDataNode.new
22
26
 
23
27
  if options[:include]
24
28
  paths = Path.parse(options[:include])
25
- included_resources = Set.new
29
+ serializers = Set.new
26
30
 
27
31
  resource.each do |r|
28
- Path.find(paths, r, included_resources)
29
-
30
- serializer =
31
- if options[:serializer]
32
- options[:serializer].new(r)
33
- else
34
- Serializer.factory(r)
35
- end
36
-
37
- node.children << ResourceNodeBuilder.build(serializer)
32
+ serializer = Serializer.factory(r, options[:serializer])
33
+ Path.find(paths, serializer, serializers)
34
+ fieldset = fieldsets[serializer.type]
35
+ node.children << ResourceNodeBuilder.build(serializer, fieldset)
38
36
  end
39
37
 
40
- root.children << IncludedNode.build(included_resources)
38
+ root.children << IncludedNodeBuilder.build(serializers, fieldsets)
41
39
  else
42
40
  resource.each do |r|
43
- serializer =
44
- if options[:serializer]
45
- options[:serializer].new(r)
46
- else
47
- Serializer.factory(r)
48
- end
49
-
50
- node.children << ResourceNodeBuilder.build(serializer)
41
+ serializer = Serializer.factory(r, options[:serializer])
42
+ fieldset = fieldsets[serializer.type]
43
+ node.children << ResourceNodeBuilder.build(serializer, fieldset)
51
44
  end
52
45
  end
53
46
 
54
47
  root.children << node
55
48
  else
56
- serializer =
57
- if options[:serializer]
58
- options[:serializer].new(resource)
59
- else
60
- Serializer.factory(resource)
61
- end
49
+ node = DataNode.new
50
+
51
+ serializer = Serializer.factory(resource, options[:serializer])
52
+ fieldset = fieldsets[serializer.type]
62
53
 
63
- root.children << DataNodeBuilder.build(serializer)
54
+ node.children << ResourceNodeBuilder.build(serializer, fieldset)
64
55
 
65
56
  if options[:include]
66
57
  paths = Path.parse(options[:include])
67
- included_resources = Set.new
68
- Path.find(paths, resource, included_resources)
69
- root.children << IncludedNodeBuilder.build(included_resources)
58
+ serializers = Set.new
59
+ Path.find(paths, serializer, serializers)
60
+ root.children << IncludedNodeBuilder.build(serializers, fieldsets)
70
61
  end
62
+
63
+ root.children << node
71
64
  end
72
65
 
73
66
  document
@@ -1,14 +1,17 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module IncludedNodeBuilder
4
- # @param [Set<Object>] resources
4
+ include Nodes
5
+
6
+ # @param [Set<Serializer>] serializers
7
+ # @param [Hash<String, String>] fieldset
5
8
  # @return [IncludedNode]
6
- def self.build(resources)
9
+ def self.build(serializers, fieldsets = {})
7
10
  node = IncludedNode.new
8
11
 
9
- resources.each do |resource|
10
- serializer = Serializer.factory(resource)
11
- node.children << ResourceNodeBuilder.build(serializer)
12
+ serializers.each do |serializer|
13
+ fieldset = fieldsets[serializer.type]
14
+ node.children << ResourceNodeBuilder.build(serializer, fieldset)
12
15
  end
13
16
 
14
17
  node
@@ -1,6 +1,8 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module LinksNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Array<Link>] links
5
7
  # @return [LinksNode]
6
8
  def self.build(links)
@@ -1,13 +1,15 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module RelationshipNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Relationship] relationship
5
7
  # @param [Serializer] serializer
6
8
  # @return [RelationshipNode]
7
9
  def self.build(relationship, serializer)
8
10
  node = RelationshipNode.new(relationship)
9
11
 
10
- if !relationship.options[:no_data]
12
+ if relationship.options[:data]
11
13
  node.children <<
12
14
  case relationship
13
15
  when BelongsToRelationship
@@ -33,7 +35,7 @@ module Jei
33
35
  node = DataNode.new
34
36
  resource = relationship.evaluate(serializer)
35
37
 
36
- serializer = Serializer.factory(resource)
38
+ serializer = Serializer.factory(resource, relationship.options[:serializer])
37
39
  node.children << ResourceIdentifierNode.new(serializer)
38
40
 
39
41
  node
@@ -47,7 +49,7 @@ module Jei
47
49
  resources = relationship.evaluate(serializer)
48
50
 
49
51
  resources.each do |resource|
50
- serializer = Serializer.factory(resource)
52
+ serializer = Serializer.factory(resource, relationship.options[:serializer])
51
53
  node.children << ResourceIdentifierNode.new(serializer)
52
54
  end
53
55
 
@@ -1,12 +1,14 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module RelationshipsNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Serializer] serializer
5
7
  # @return [RelationshipsNode]
6
- def self.build(serializer)
8
+ def self.build(relationships, serializer)
7
9
  node = RelationshipsNode.new
8
10
 
9
- serializer.relationships.values.each do |relationship|
11
+ relationships.each do |relationship|
10
12
  node.children << RelationshipNodeBuilder.build(relationship, serializer)
11
13
  end
12
14
 
@@ -1,19 +1,26 @@
1
1
  module Jei
2
- module Builder
2
+ module Builders
3
3
  module ResourceNodeBuilder
4
+ include Nodes
5
+
4
6
  # @param [Serializer] serializer
7
+ # @param [Array<Symbol>] fieldset
5
8
  # @return [ResourceNode]
6
- def self.build(serializer)
9
+ def self.build(serializer, fieldset = nil)
7
10
  node = ResourceNode.new
8
11
 
9
12
  node.children << ResourceIdentifierNode.new(serializer)
10
13
 
11
- if serializer.attributes.any?
12
- node.children << AttributesNodeBuilder.build(serializer)
14
+ attributes = serializer.attributes(fieldset).values
15
+
16
+ if attributes.any?
17
+ node.children << AttributesNodeBuilder.build(attributes, serializer)
13
18
  end
14
19
 
15
- if serializer.relationships.any?
16
- node.children << RelationshipsNodeBuilder.build(serializer)
20
+ relationships = serializer.relationships(fieldset).values
21
+
22
+ if relationships.any?
23
+ node.children << RelationshipsNodeBuilder.build(relationships, serializer)
17
24
  end
18
25
 
19
26
  links = serializer.links
data/lib/jei/document.rb CHANGED
@@ -6,23 +6,27 @@ module Jei
6
6
  # @return [DocumentNode]
7
7
  attr_reader :root
8
8
 
9
+ # Builds a document from a resource.
10
+ #
9
11
  # @param [Object] resource
10
12
  # @param [Hash<Symbol, Object>] options
11
- # @option options [Boolean] :jsonapi Add the top level JSON API object to
12
- # the document.
13
- # @option options [Array<Link>] :links Add links related to the primary
14
- # data.
15
- # @option options [Hash<Symbol, Object>] :meta Add top level meta
16
- # information to the document.
17
- # @option options [Class] :serializer Override the default serializer. For
18
- # collections, this works only if all the resources are of the same type.
13
+ # @option options [Hash<String, String>] :fields restrict resource
14
+ # attributes and relationships to a user-defined set of fields
15
+ # @option options [String] :include a list of relationship paths
16
+ # @option options [Boolean] :jsonapi add the top level JSON API object to
17
+ # the document
18
+ # @option options [Array<Link>] :links add links related to the primary
19
+ # data
20
+ # @option options [Hash<Symbol, Object>] :meta add top level meta
21
+ # information to the document
22
+ # @option options [Class] :serializer override the default serializer
19
23
  # @return [Document]
20
24
  def self.build(resource, options = {})
21
- Builder::DocumentBuilder.build(resource, options)
25
+ Builders::DocumentBuilder.build(resource, options)
22
26
  end
23
27
 
24
28
  def initialize
25
- @root = DocumentNode.new
29
+ @root = Nodes::DocumentNode.new
26
30
  end
27
31
 
28
32
  # @return [Hash<Symbol, Object>]
data/lib/jei/error.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Jei
2
+ class Error < RuntimeError
3
+ end
4
+ end
data/lib/jei/field.rb ADDED
@@ -0,0 +1,22 @@
1
+ module Jei
2
+ class Field
3
+ # @return [Symbol]
4
+ attr_reader :name
5
+
6
+ # @param [Symbol] name
7
+ # @param [Proc, Symbol] value
8
+ def initialize(name, value = name)
9
+ @name = name
10
+ @value = value
11
+ end
12
+
13
+ # @param [Serializer] serializer
14
+ def evaluate(serializer)
15
+ if @value.is_a?(Proc)
16
+ serializer.instance_eval(&@value)
17
+ else
18
+ serializer.resource.send(@value)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Jei
2
+ class Fieldset
3
+ NAME_SEPARATOR = ','
4
+
5
+ def self.parse(raw_fields)
6
+ fields = {}
7
+
8
+ raw_fields.each do |type, names|
9
+ fields[type] = names.split(NAME_SEPARATOR).map(&:to_sym)
10
+ end
11
+
12
+ fields
13
+ end
14
+ end
15
+ end
@@ -1,17 +1,19 @@
1
1
  module Jei
2
- # @see http://jsonapi.org/format/1.0/#document-resource-object-attributes
3
- class AttributeNode < Node
4
- # @param [Serializer] serializer
5
- # @param [Attribute] attribute
6
- def initialize(serializer, attribute)
7
- super()
8
- @serializer = serializer
9
- @attribute = attribute
10
- end
2
+ module Nodes
3
+ # @see http://jsonapi.org/format/1.0/#document-resource-object-attributes
4
+ class AttributeNode < Node
5
+ # @param [Serializer] serializer
6
+ # @param [Attribute] attribute
7
+ def initialize(serializer, attribute)
8
+ super()
9
+ @serializer = serializer
10
+ @attribute = attribute
11
+ end
11
12
 
12
- # @param [Hash<Symbol, Object>] context
13
- def visit(context)
14
- context[@attribute.name] = @attribute.evaluate(@serializer)
13
+ # @param [Hash<Symbol, Object>] context
14
+ def visit(context)
15
+ context[@attribute.name] = @attribute.evaluate(@serializer)
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -1,11 +1,13 @@
1
1
  module Jei
2
- # @see http://jsonapi.org/format/1.0/#document-resource-object-attributes
3
- class AttributesNode < Node
4
- # @param [Hash<Symbol, Object>] context
5
- def visit(context)
6
- attributes = {}
7
- children.each { |child| child.visit(attributes) }
8
- context[:attributes] = attributes
2
+ module Nodes
3
+ # @see http://jsonapi.org/format/1.0/#document-resource-object-attributes
4
+ class AttributesNode < Node
5
+ # @param [Hash<Symbol, Object>] context
6
+ def visit(context)
7
+ attributes = {}
8
+ children.each { |child| child.visit(attributes) }
9
+ context[:attributes] = attributes
10
+ end
9
11
  end
10
12
  end
11
13
  end