simple_json_api 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d342c421da25b887edeade3d14b1a145bbe3a352
4
- data.tar.gz: 2720735c97db2a23d45ac6154460f2c92f8dfa67
3
+ metadata.gz: 75b1e1d7eab7671430dab2b735ea9b3ce3d0b921
4
+ data.tar.gz: 04ad4e30da53078764dbafa68edab1ca81f579b5
5
5
  SHA512:
6
- metadata.gz: 87165f1029afae88c79cae12d06d502ad77fe55c6d2a68cdb02b6446ef757b73cc2ea3e0906418083ba1f358f5a79a88a7348acdb8754227e6d24c65f9182038
7
- data.tar.gz: 7f0428e1ab60247971c0ef04ad4a09a156ab62c5c784473024c90da6809ec6656fd77b006025593aa3b021852219830f585cbd004e401544a07a6c905fd2e825
6
+ metadata.gz: e8eabae974ab4bf5aa7775b59bd2af0ae6a27ca46e72aaf8be3831ad586d040b6f28a2b400e51c78efff351b1168602cf7d4f841c01b202596833f3f840197ea
7
+ data.tar.gz: 43ff3b97dc119fcf716b5a4890785321bfe7077cbfdbc7e79a9d4d1449fb5b100b6d2defde06de30ab05d1be079b8f71ec74d8328d6c1255d5864da7fadaa159
data/.travis.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1
4
- - 2.2
4
+ - 2.2.1
5
5
  env:
6
6
  - 'RAILS_VERSION=4.0'
7
7
  - 'RAILS_VERSION=4.1'
data/README.md CHANGED
@@ -20,6 +20,11 @@ Or install it yourself as:
20
20
 
21
21
  $ gem install simple_json_api
22
22
 
23
+
24
+ ### Rails Integration
25
+
26
+ Use the gem [simple_json_api-rails](https://github.com/dajacques/simple_json_api-rails)
27
+
23
28
  ## Usage
24
29
 
25
30
  ### Define serializers
@@ -59,6 +64,7 @@ render json: SimpleJsonApi.render(
59
64
  When rendering the model is the AR data to be serialized, if it is an Array the ArraySerializer will be used for the top collection.
60
65
  `fields` and `include` follow the jsonapi spec. [Include](http://jsonapi.org/format/#fetching-includes) will be the associations to be included in the generated json. [Fields](http://jsonapi.org/format/#fetching-sparse-fieldsets) is the list of attributes that will be included. The primary key will always be included.
61
66
 
67
+
62
68
  ## TODO
63
69
 
64
70
  0. Better documentation
@@ -20,6 +20,10 @@ module SimpleJsonApi
20
20
  @associations = [] # list of api_nodes
21
21
  end
22
22
 
23
+ def collection?
24
+ @serializer.is_a? ArraySerializer
25
+ end
26
+
23
27
  def load
24
28
  return self unless serializer_actual._associations
25
29
  serializer_actual._associations.each do |association|
@@ -29,27 +33,35 @@ module SimpleJsonApi
29
33
  end
30
34
 
31
35
  def serializer_actual
32
- @serializer_actual ||= @each_serializer || self.serializer
36
+ @serializer_actual ||= @each_serializer || serializer
33
37
  end
34
38
 
35
39
  def add_association(association)
36
40
  return unless @assoc_list.key? association.plural_name
37
41
  resource = serializer.associated_object(association.name)
38
42
  Array(resource).each do |object|
39
- each_serializer = Serializer.for(object, association)
40
- serializer = SerializerFactory.create(
41
- object, each_serializer, self.serializer._builder
42
- )
43
- self <<
44
- ApiNode.new(
45
- association.plural_name,
46
- serializer,
47
- @assoc_list[association.plural_name],
48
- serializer._each_serializer
49
- ).load
43
+ add_nodes(association, object)
50
44
  end
51
45
  end
52
46
 
47
+ def add_nodes(association, object)
48
+ each_serializer = Serializer.for(object, association)
49
+ serializer = SerializerFactory.create(
50
+ object, each_serializer, self.serializer._builder
51
+ )
52
+ add_node(association, serializer)
53
+ end
54
+
55
+ def add_node(association, serializer)
56
+ self <<
57
+ ApiNode.new(
58
+ association.plural_name,
59
+ serializer,
60
+ @assoc_list[association.plural_name],
61
+ serializer._each_serializer
62
+ ).load
63
+ end
64
+
53
65
  def <<(node)
54
66
  add_assoc(node)
55
67
  end
@@ -59,7 +71,8 @@ module SimpleJsonApi
59
71
  end
60
72
 
61
73
  # def display(offset = '')
62
- # ap "DISPLAY: #{offset}#{@name}, #{@assoc_list}, #{Array(@object).first.class}, #{Array(@object).map(&:id)}"
74
+ # ap "DISPLAY: #{offset}#{@name}, #{@assoc_list}, \
75
+ # #{Array(@object).first.class}, #{Array(@object).map(&:id)}"
63
76
  # @associations.each do |assoc|
64
77
  # assoc.display(offset + ' ')
65
78
  # end
@@ -19,17 +19,20 @@ module SimpleJsonApi
19
19
  def_delegators :@field_list, :fields_for
20
20
 
21
21
  # TODO: sort: nil
22
- def initialize(object, wrapper, serializer, fields, include)
22
+ def initialize(object, wrapper, serializer, fields, include, page)
23
23
  @object = object
24
24
  @wrapper = wrapper
25
25
  @field_list = FieldList.new(fields, serializer)
26
26
  @include = IncludeList.new(include).parse
27
+ @page = page
27
28
  @serializer = SerializerFactory.create(object, serializer, self)
28
29
  end
29
30
 
30
31
  def as_json(options = nil)
31
- root_node = ApiNode.new(serializer._root_name, serializer, include.include_hash).load
32
- wrapper.new(root_node).as_json(options)
32
+ root_node = ApiNode.new(
33
+ serializer._root_name, serializer, include.include_hash
34
+ ).load
35
+ wrapper.new(root_node, @page).as_json(options)
33
36
  end
34
37
  end
35
38
  end
@@ -69,14 +69,15 @@ module SimpleJsonApi
69
69
  define_assoc_method(association) # unless defined? association.name
70
70
  end
71
71
 
72
- def define_assoc_method(association)
73
- if association.type == :has_many
74
- define_method association.name do |includes = nil|
75
- _object.send(association.name).includes(includes).to_a if _object.respond_to?(association.name)
72
+ def define_assoc_method(assoc)
73
+ if assoc.type == :has_many
74
+ define_method assoc.name do |includes = nil|
75
+ _object.send(assoc.name).includes(includes).to_a \
76
+ if _object.respond_to?(assoc.name)
76
77
  end
77
78
  else
78
- define_method association.name do |includes = nil|
79
- _object.send(association.name) if _object.respond_to?(association.name)
79
+ define_method assoc.name do |_includes = nil|
80
+ _object.send(assoc.name) if _object.respond_to?(assoc.name)
80
81
  end
81
82
  end
82
83
  end
@@ -6,8 +6,9 @@ require 'simple_json_api/member/meta'
6
6
  module SimpleJsonApi
7
7
  # JSONAPI Wrapper
8
8
  class JsonApiWrapper
9
- def initialize(root_node)
9
+ def initialize(root_node, page)
10
10
  @root_node = root_node
11
+ @page = page
11
12
  @result = {}
12
13
  end
13
14
 
@@ -27,7 +28,8 @@ module SimpleJsonApi
27
28
  end
28
29
 
29
30
  def links
30
- @result[:links] ||= Member::Links.new.content
31
+ page = @root_node.collection? ? @page : {}
32
+ @result[:links] ||= Member::Links.new(page).content
31
33
  end
32
34
 
33
35
  def meta
@@ -2,7 +2,12 @@ module SimpleJsonApi
2
2
  module Member
3
3
  # JSONAPI Links top-level member
4
4
  class Links
5
+ def initialize(page)
6
+ @page = page
7
+ end
8
+
5
9
  def content
10
+ { page: @page } if @page.present?
6
11
  end
7
12
  end
8
13
  end
@@ -7,7 +7,7 @@ module SimpleJsonApi
7
7
  module ActiveRecord
8
8
  refine ::ActiveRecord::Base do
9
9
  def typed_json_id
10
- [self.class.to_s.downcase.pluralize, json_id]
10
+ { type: self.class.to_s.downcase.pluralize, id: json_id }
11
11
  end
12
12
 
13
13
  def json_id
@@ -4,7 +4,7 @@ module SimpleJsonApi
4
4
  # Refinements on Array
5
5
  module Array
6
6
  refine ::Array do
7
- def includes(includes = nil)
7
+ def includes(_includes = nil)
8
8
  self
9
9
  end
10
10
  end
@@ -40,10 +40,10 @@ module SimpleJsonApi
40
40
  _fields.each do |attribute, _attr_opts|
41
41
  hash[attribute] = send(attribute).to_s
42
42
  end
43
- hash[:href] = href if self.class.method_defined? :href
44
43
  end
45
44
 
46
45
  def link_values(root)
46
+ root[:self] = href if self.class.method_defined? :href
47
47
  self.class._associations.each do |association|
48
48
  root[association.key] = link(association)
49
49
  end
@@ -51,14 +51,33 @@ module SimpleJsonApi
51
51
 
52
52
  def link(association)
53
53
  if association.type == :has_many
54
- includes = association.polymorphic ? [] : Serializer.includes(association)
55
- resource = send(association.name, includes)
56
- resource.map do |obj|
57
- association[:polymorphic] ? obj.typed_json_id : obj.json_id
58
- end
54
+ link_many(association)
59
55
  else
60
- resource = send(association.name)
61
- resource.json_id if resource
56
+ link_one(association)
57
+ end
58
+ end
59
+
60
+ def link_many(association)
61
+ resource = send(association.name, includes(association))
62
+ { linkage: linkage_values(resource) }
63
+ end
64
+
65
+ def link_one(association)
66
+ resource = send(association.name)
67
+ { linkage: resource.typed_json_id } if resource
68
+ end
69
+
70
+ def linkage_values(resource)
71
+ resource.map do |obj|
72
+ obj.typed_json_id
73
+ end
74
+ end
75
+
76
+ def includes(association)
77
+ if association.polymorphic
78
+ []
79
+ else
80
+ Serializer.includes(association)
62
81
  end
63
82
  end
64
83
 
@@ -40,10 +40,10 @@ module SimpleJsonApi
40
40
  def builder_fields
41
41
  bf = _builder.fields_for(_root_name).presence
42
42
  fields = if bf.present?
43
- (required_fields + Array(bf)).uniq
44
- else
45
- default_fields ? default_fields & all_fields : all_fields
46
- end
43
+ (required_fields + Array(bf)).uniq
44
+ else
45
+ default_fields ? default_fields & all_fields : all_fields
46
+ end
47
47
  (required_fields + Array(fields)).uniq.map(&:to_sym)
48
48
  end
49
49
 
@@ -67,7 +67,9 @@ module SimpleJsonApi
67
67
 
68
68
  def includes(association)
69
69
  serializer = Serializer.for_regular(association)
70
- serializer._associations.reject(&:polymorphic).map { |a| a[:name] } if serializer
70
+ serializer._associations.reject(&:polymorphic).map do |assoc|
71
+ assoc[:name]
72
+ end if serializer
71
73
  end
72
74
 
73
75
  def for_regular(association)
@@ -1,4 +1,4 @@
1
1
  # SimpleJsonApi
2
2
  module SimpleJsonApi
3
- VERSION = '0.0.4'
3
+ VERSION = '0.0.5'
4
4
  end
@@ -10,7 +10,7 @@ require 'simple_json_api/helper'
10
10
  # SimpleJsonApi
11
11
  module SimpleJsonApi
12
12
  # Main hook to generate json
13
- def self.render(model:, serializer:, fields: nil, include: nil, wrapper: JsonApiWrapper)
14
- Builder.new(model, wrapper, serializer, fields, include).to_json
13
+ def self.render(model:, serializer:, fields: nil, include: nil, page: {}, wrapper: JsonApiWrapper)
14
+ Builder.new(model, wrapper, serializer, fields, include, page).to_json
15
15
  end
16
16
  end
@@ -25,10 +25,16 @@ module SimpleJsonApi
25
25
  'name' => 'First Project',
26
26
  'description' => 'The first project',
27
27
  'position' => '',
28
- 'href' => 'http://example.com/projects/100',
29
28
  'links' => {
30
- 'todolist' => '200',
31
- 'tags' => %w(10)
29
+ 'self' => 'http://example.com/projects/100',
30
+ 'todolist' => {
31
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
32
+ },
33
+ 'tags' => {
34
+ 'linkage' => [
35
+ { 'type' => 'tags', 'id' => '10' }
36
+ ]
37
+ }
32
38
  }
33
39
  }
34
40
  }
@@ -49,10 +55,16 @@ module SimpleJsonApi
49
55
  'name' => 'First Project',
50
56
  'description' => 'The first project',
51
57
  'position' => '',
52
- 'href' => 'http://example.com/projects/100',
53
58
  'links' => {
54
- 'todolist' => '200',
55
- 'tags' => %w(10)
59
+ 'self' => 'http://example.com/projects/100',
60
+ 'todolist' => {
61
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
62
+ },
63
+ 'tags' => {
64
+ 'linkage' => [
65
+ { 'type' => 'tags', 'id' => '10' }
66
+ ]
67
+ }
56
68
  }
57
69
  },
58
70
  {
@@ -61,10 +73,16 @@ module SimpleJsonApi
61
73
  'name' => 'Second Project',
62
74
  'description' => 'The second project',
63
75
  'position' => '',
64
- 'href' => 'http://example.com/projects/110',
65
76
  'links' => {
66
- 'todolist' => '210',
67
- 'tags' => %w(20)
77
+ 'self' => 'http://example.com/projects/110',
78
+ 'todolist' => {
79
+ 'linkage' => { 'type' => 'todolists', 'id' => '210' }
80
+ },
81
+ 'tags' => {
82
+ 'linkage' => [
83
+ { 'type' => 'tags', 'id' => '20' }
84
+ ]
85
+ }
68
86
  }
69
87
  }
70
88
  ]
@@ -29,10 +29,16 @@ module SimpleJsonApi
29
29
  'id' => '100',
30
30
  'name' => 'First Project',
31
31
  'description' => 'The first project',
32
- 'href' => 'http://example.com/projects/100',
33
32
  'links' => {
34
- 'todolist' => '200',
35
- 'tags' => ['10']
33
+ 'self' => 'http://example.com/projects/100',
34
+ 'todolist' => {
35
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
36
+ },
37
+ 'tags' => {
38
+ 'linkage' => [
39
+ { 'type' => 'tags', 'id' => '10' }
40
+ ]
41
+ }
36
42
  }
37
43
  }
38
44
  }
@@ -53,10 +59,16 @@ module SimpleJsonApi
53
59
  'id' => '100',
54
60
  'name' => 'First Project',
55
61
  'description' => 'The first project',
56
- 'href' => 'http://example.com/projects/100',
57
62
  'links' => {
58
- 'todolist' => '200',
59
- 'tags' => ['10']
63
+ 'self' => 'http://example.com/projects/100',
64
+ 'todolist' => {
65
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
66
+ },
67
+ 'tags' => {
68
+ 'linkage' => [
69
+ { 'type' => 'tags', 'id' => '10' }
70
+ ]
71
+ }
60
72
  }
61
73
  },
62
74
  {
@@ -64,10 +76,16 @@ module SimpleJsonApi
64
76
  'id' => '110',
65
77
  'name' => 'Second Project',
66
78
  'description' => 'The second project',
67
- 'href' => 'http://example.com/projects/110',
68
79
  'links' => {
69
- 'todolist' => '210',
70
- 'tags' => ['20']
80
+ 'self' => 'http://example.com/projects/110',
81
+ 'todolist' => {
82
+ 'linkage' => { 'type' => 'todolists', 'id' => '210' }
83
+ },
84
+ 'tags' => {
85
+ 'linkage' => [
86
+ { 'type' => 'tags', 'id' => '20' }
87
+ ]
88
+ }
71
89
  }
72
90
  }
73
91
  ]
@@ -86,9 +104,14 @@ module SimpleJsonApi
86
104
  'type' => 'todos',
87
105
  'id' => '300',
88
106
  'action' => 'Milk',
89
- 'href' => 'http://example.com/todos/300',
90
107
  'links' => {
91
- 'tags' => %w(10 30)
108
+ 'self' => 'http://example.com/todos/300',
109
+ 'tags' => {
110
+ 'linkage' => [
111
+ { 'type' => 'tags', 'id' => '10' },
112
+ { 'type' => 'tags', 'id' => '30' }
113
+ ]
114
+ }
92
115
  }
93
116
  }
94
117
  }
@@ -26,10 +26,16 @@ module SimpleJsonApi
26
26
  'name' => 'First Project',
27
27
  'description' => 'The first project',
28
28
  'position' => '',
29
- 'href' => 'http://example.com/projects/100',
30
29
  'links' => {
31
- 'todolist' => '200',
32
- 'tags' => ['10']
30
+ 'self' => 'http://example.com/projects/100',
31
+ 'todolist' => {
32
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
33
+ },
34
+ 'tags' => {
35
+ 'linkage' => [
36
+ { 'type' => 'tags', 'id' => '10' }
37
+ ]
38
+ }
33
39
  }
34
40
  },
35
41
  'included' => [
@@ -37,10 +43,19 @@ module SimpleJsonApi
37
43
  'type' => 'todolists',
38
44
  'id' => '200',
39
45
  'description' => 'Groceries',
40
- 'href' => 'http://example.com/todolists/200',
41
46
  'links' => {
42
- 'todos' => %w(300 301),
43
- 'tags' => ['30']
47
+ 'self' => 'http://example.com/todolists/200',
48
+ 'todos' => {
49
+ 'linkage' => [
50
+ { 'type' => 'todos', 'id' => '300' },
51
+ { 'type' => 'todos', 'id' => '301' }
52
+ ]
53
+ },
54
+ 'tags' => {
55
+ 'linkage' => [
56
+ { 'type' => 'tags', 'id' => '30' }
57
+ ]
58
+ }
44
59
  }
45
60
  }
46
61
  ]
@@ -63,10 +78,16 @@ module SimpleJsonApi
63
78
  'name' => 'First Project',
64
79
  'description' => 'The first project',
65
80
  'position' => '',
66
- 'href' => 'http://example.com/projects/100',
67
81
  'links' => {
68
- 'todolist' => '200',
69
- 'tags' => ['10']
82
+ 'self' => 'http://example.com/projects/100',
83
+ 'todolist' => {
84
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
85
+ },
86
+ 'tags' => {
87
+ 'linkage' => [
88
+ { 'type' => 'tags', 'id' => '10' }
89
+ ]
90
+ }
70
91
  }
71
92
  },
72
93
  {
@@ -75,10 +96,16 @@ module SimpleJsonApi
75
96
  'name' => 'Second Project',
76
97
  'description' => 'The second project',
77
98
  'position' => '',
78
- 'href' => 'http://example.com/projects/110',
79
99
  'links' => {
80
- 'todolist' => '210',
81
- 'tags' => ['20']
100
+ 'self' => 'http://example.com/projects/110',
101
+ 'todolist' => {
102
+ 'linkage' => { 'type' => 'todolists', 'id' => '210' }
103
+ },
104
+ 'tags' => {
105
+ 'linkage' => [
106
+ { 'type' => 'tags', 'id' => '20' }
107
+ ]
108
+ }
82
109
  }
83
110
  }
84
111
  ],
@@ -87,10 +114,19 @@ module SimpleJsonApi
87
114
  'type' => 'todolists',
88
115
  'id' => '200',
89
116
  'description' => 'Groceries',
90
- 'href' => 'http://example.com/todolists/200',
91
117
  'links' => {
92
- 'todos' => %w(300 301),
93
- 'tags' => ['30']
118
+ 'self' => 'http://example.com/todolists/200',
119
+ 'todos' => {
120
+ 'linkage' => [
121
+ { 'type' => 'todos', 'id' => '300' },
122
+ { 'type' => 'todos', 'id' => '301' }
123
+ ]
124
+ },
125
+ 'tags' => {
126
+ 'linkage' => [
127
+ { 'type' => 'tags', 'id' => '30' }
128
+ ]
129
+ }
94
130
  }
95
131
  },
96
132
  {
@@ -98,10 +134,18 @@ module SimpleJsonApi
98
134
  'id' => '210',
99
135
  'description' => 'Groceries',
100
136
  'description' => 'Work',
101
- 'href' => 'http://example.com/todolists/210',
102
137
  'links' => {
103
- 'todos' => %w(310 320 330),
104
- 'tags' => []
138
+ 'self' => 'http://example.com/todolists/210',
139
+ 'todos' => {
140
+ 'linkage' => [
141
+ { 'type' => 'todos', 'id' => '310' },
142
+ { 'type' => 'todos', 'id' => '320' },
143
+ { 'type' => 'todos', 'id' => '330' }
144
+ ]
145
+ },
146
+ 'tags' => {
147
+ 'linkage' => []
148
+ }
105
149
  }
106
150
  },
107
151
  {
@@ -110,12 +154,14 @@ module SimpleJsonApi
110
154
  'guid' => '10',
111
155
  'name' => 'Urgent!',
112
156
  'links' => {
113
- 'taggables' => [
114
- %w(projects 100),
115
- %w(todos 300),
116
- %w(todos 301),
117
- %w(todos 330)
118
- ]
157
+ 'taggables' => {
158
+ 'linkage' => [
159
+ { 'type' => 'projects', 'id' => '100' },
160
+ { 'type' => 'todos', 'id' => '300' },
161
+ { 'type' => 'todos', 'id' => '301' },
162
+ { 'type' => 'todos', 'id' => '330' }
163
+ ]
164
+ }
119
165
  }
120
166
  },
121
167
  {
@@ -124,9 +170,11 @@ module SimpleJsonApi
124
170
  'guid' => '20',
125
171
  'name' => 'On Hold',
126
172
  'links' => {
127
- 'taggables' => [
128
- %w(projects 110)
129
- ]
173
+ 'taggables' => {
174
+ 'linkage' => [
175
+ { 'type' => 'projects', 'id' => '110' }
176
+ ]
177
+ }
130
178
  }
131
179
  }
132
180
  ]
@@ -24,44 +24,72 @@ module SimpleJsonApi
24
24
  'data' => {
25
25
  'type' => 'projects',
26
26
  'id' => '100',
27
- 'href' => 'http://example.com/projects/100',
28
27
  'links' => {
29
- 'todolist' => '200',
30
- 'tags' => ['10']
28
+ 'self' => 'http://example.com/projects/100',
29
+ 'todolist' => {
30
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
31
+ },
32
+ 'tags' => {
33
+ 'linkage' => [
34
+ { 'type' => 'tags', 'id' => '10' }
35
+ ]
36
+ }
31
37
  }
32
38
  },
33
39
  'included' => [
34
40
  {
35
41
  'type' => 'todolists',
36
42
  'id' => '200',
37
- 'href' => 'http://example.com/todolists/200',
38
43
  'links' => {
39
- 'todos' => %w(300 301),
40
- 'tags' => ['30']
44
+ 'self' => 'http://example.com/todolists/200',
45
+ 'todos' => {
46
+ 'linkage' => [
47
+ { 'type' => 'todos', 'id' => '300' },
48
+ { 'type' => 'todos', 'id' => '301' }
49
+ ]
50
+ },
51
+ 'tags' => {
52
+ 'linkage' => [
53
+ { 'type' => 'tags', 'id' => '30' }
54
+ ]
55
+ }
41
56
  }
42
57
  },
43
58
  {
44
59
  'type' => 'todos',
45
60
  'id' => '300',
46
- 'href' => 'http://example.com/todos/300',
47
61
  'links' => {
48
- 'tags' => %w(10 30)
62
+ 'self' => 'http://example.com/todos/300',
63
+ 'tags' => {
64
+ 'linkage' => [
65
+ { 'type' => 'tags', 'id' => '10' },
66
+ { 'type' => 'tags', 'id' => '30' }
67
+ ]
68
+ }
49
69
  }
50
70
  },
51
71
  {
52
72
  'type' => 'todos',
53
73
  'id' => '301',
54
- 'href' => 'http://example.com/todos/301',
55
74
  'links' => {
56
- 'tags' => %w(10)
75
+ 'self' => 'http://example.com/todos/301',
76
+ 'tags' => {
77
+ 'linkage' => [
78
+ { 'type' => 'tags', 'id' => '10' }
79
+ ]
80
+ }
57
81
  }
58
82
  },
59
83
  {
60
84
  'type' => 'todos',
61
85
  'id' => '330',
62
- 'href' => 'http://example.com/todos/330',
63
86
  'links' => {
64
- 'tags' => %w(10)
87
+ 'self' => 'http://example.com/todos/330',
88
+ 'tags' => {
89
+ 'linkage' => [
90
+ { 'type' => 'tags', 'id' => '10' }
91
+ ]
92
+ }
65
93
  }
66
94
  }
67
95
  ]
@@ -0,0 +1,101 @@
1
+ require 'test_helper'
2
+
3
+ # SimpleJsonApi
4
+ module SimpleJsonApi
5
+ describe 'RenderPaginationTest' do
6
+ it 'should match json hash for a project with no options' do
7
+ actual_project.must_match_json expected_project
8
+ end
9
+
10
+ it 'should match json hash for a project array with no options' do
11
+ actual_projects.must_match_json expected_projects
12
+ end
13
+
14
+ let(:actual_project) do
15
+ SimpleJsonApi.render(
16
+ model: Project.first,
17
+ serializer: ProjectSerializer,
18
+ page: { number: 5, size: 20, total: 19 }
19
+ )
20
+ end
21
+ let(:expected_project) do
22
+ {
23
+ 'data' => {
24
+ 'type' => 'projects',
25
+ 'id' => '100',
26
+ 'name' => 'First Project',
27
+ 'description' => 'The first project',
28
+ 'position' => '',
29
+ 'links' => {
30
+ 'self' => 'http://example.com/projects/100',
31
+ 'todolist' => {
32
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
33
+ },
34
+ 'tags' => {
35
+ 'linkage' => [
36
+ { 'type' => 'tags', 'id' => '10' }
37
+ ]
38
+ }
39
+ }
40
+ }
41
+ }
42
+ end
43
+
44
+ let(:actual_projects) do
45
+ SimpleJsonApi.render(
46
+ model: Project.all.to_a,
47
+ serializer: ProjectSerializer,
48
+ page: { number: 5, size: 20, total: 19 }
49
+ )
50
+ end
51
+ let(:expected_projects) do
52
+ {
53
+ 'links' => {
54
+ 'page' => {
55
+ 'number' => 5,
56
+ 'size' => 20,
57
+ 'total' => 19
58
+ }
59
+ },
60
+ 'data' => [
61
+ {
62
+ 'type' => 'projects',
63
+ 'id' => '100',
64
+ 'name' => 'First Project',
65
+ 'description' => 'The first project',
66
+ 'position' => '',
67
+ 'links' => {
68
+ 'self' => 'http://example.com/projects/100',
69
+ 'todolist' => {
70
+ 'linkage' => { 'type' => 'todolists', 'id' => '200' }
71
+ },
72
+ 'tags' => {
73
+ 'linkage' => [
74
+ { 'type' => 'tags', 'id' => '10' }
75
+ ]
76
+ }
77
+ }
78
+ },
79
+ {
80
+ 'type' => 'projects',
81
+ 'id' => '110',
82
+ 'name' => 'Second Project',
83
+ 'description' => 'The second project',
84
+ 'position' => '',
85
+ 'links' => {
86
+ 'self' => 'http://example.com/projects/110',
87
+ 'todolist' => {
88
+ 'linkage' => { 'type' => 'todolists', 'id' => '210' }
89
+ },
90
+ 'tags' => {
91
+ 'linkage' => [
92
+ { 'type' => 'tags', 'id' => '20' }
93
+ ]
94
+ }
95
+ }
96
+ }
97
+ ]
98
+ }
99
+ end
100
+ end
101
+ end
data/test/setup/data.rb CHANGED
@@ -20,7 +20,6 @@ todo1.tags << tag3
20
20
  todo2 = list1.todos.create(id: 301, action: 'Bread')
21
21
  todo2.tags << tag1
22
22
 
23
-
24
23
  list2 = project2.create_todolist(id: 210, description: 'Work')
25
24
  list2.todos.create(id: 310, action: 'Timesheet')
26
25
  list2.todos.create(id: 320, action: 'Meeting')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_json_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gary Gordon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-20 00:00:00.000000000 Z
11
+ date: 2015-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -68,10 +68,6 @@ files:
68
68
  - LICENSE.txt
69
69
  - README.md
70
70
  - Rakefile
71
- - lib/generators/simple_json_api/resource/USAGE
72
- - lib/generators/simple_json_api/resource/resource_generator.rb
73
- - lib/generators/simple_json_api/resource/templates/controller_template.rb.erb
74
- - lib/generators/simple_json_api/resource/templates/serializer_template.rb.erb
75
71
  - lib/simple_json_api.rb
76
72
  - lib/simple_json_api/api_node.rb
77
73
  - lib/simple_json_api/array_serializer.rb
@@ -97,11 +93,11 @@ files:
97
93
  - lib/simple_json_api/version.rb
98
94
  - simple_json_api.gemspec
99
95
  - test/fixtures/projects.yml
100
- - test/generators/simple_json_api/resource_generator_test.rb
101
96
  - test/integration/render_basic_test.rb
102
97
  - test/integration/render_fields_test.rb
103
98
  - test/integration/render_include_test.rb
104
99
  - test/integration/render_nested_include_test.rb
100
+ - test/integration/render_pagination_test.rb
105
101
  - test/integration/serializers_test.rb
106
102
  - test/setup/data.rb
107
103
  - test/setup/models.rb
@@ -135,17 +131,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
131
  version: '0'
136
132
  requirements: []
137
133
  rubyforge_project:
138
- rubygems_version: 2.4.5
134
+ rubygems_version: 2.4.6
139
135
  signing_key:
140
136
  specification_version: 4
141
137
  summary: A Simple JSON API Serializer.
142
138
  test_files:
143
139
  - test/fixtures/projects.yml
144
- - test/generators/simple_json_api/resource_generator_test.rb
145
140
  - test/integration/render_basic_test.rb
146
141
  - test/integration/render_fields_test.rb
147
142
  - test/integration/render_include_test.rb
148
143
  - test/integration/render_nested_include_test.rb
144
+ - test/integration/render_pagination_test.rb
149
145
  - test/integration/serializers_test.rb
150
146
  - test/setup/data.rb
151
147
  - test/setup/models.rb
@@ -1,8 +0,0 @@
1
- Description:
2
- Explain the generator
3
-
4
- Example:
5
- rails generate simple_json_api:resource resource
6
-
7
- This will create:
8
- what/will/it/create
@@ -1,73 +0,0 @@
1
- module SimpleJsonApi
2
- module Generators
3
- # Generates the resource template files
4
- class ResourceGenerator < Rails::Generators::NamedBase
5
- source_root File.expand_path('../templates', __FILE__)
6
-
7
- argument :name, type: :string, required: true, banner: 'ResourceName'
8
-
9
- class_option :model,
10
- desc: 'Model class if different than Resource',
11
- type: :string
12
- class_option :namespace,
13
- desc: 'Namespace for the generated files',
14
- type: :string
15
- class_option :controller,
16
- desc: 'Base controller for resources',
17
- type: :string
18
- class_option :skip_serializer,
19
- desc: "Don't generate a serializer file.",
20
- type: :boolean
21
- class_option :skip_controller,
22
- desc: "Don't generate a controller file.",
23
- type: :boolean
24
- class_option :skip_service,
25
- desc: "Don't generate a service file.",
26
- type: :boolean
27
- class_option :root_dir,
28
- desc: "Root dir for generated code, default: '.'.",
29
- type: :string
30
-
31
- def create_resource
32
- @namespace = options[:namespace]
33
- @model = options[:model] || class_name
34
- namespaced_name = [@namespace, class_name].compact.join('::')
35
- @serializer_name = "#{namespaced_name}Serializer"
36
- @controller_name = "#{namespaced_name.pluralize}Controller"
37
- @base_controller = options[:controller] || 'ApplicationController'
38
- @root_dir = options[:root_dir] || '.'
39
- file_path = "#{@namespace.underscore}/#{class_name.underscore}"
40
-
41
- check_model
42
-
43
- unless options[:skip_serializer]
44
- template 'serializer_template.rb.erb',
45
- "#{@root_dir}/app/serializers/#{file_path}_serializer.rb"
46
- # TODO: create serializer test
47
- end
48
-
49
- unless options[:skip_controller]
50
- template 'controller_template.rb.erb',
51
- "#{@root_dir}/app/controllers/#{file_path.pluralize}_controller.rb"
52
- # TODO: create controller test
53
- end
54
-
55
- unless options[:skip_service]
56
- # TODO: create service
57
- # TODO: create service test
58
- end
59
- end
60
-
61
- private
62
-
63
- def check_model
64
- unless @model.constantize.ancestors.include?(ActiveRecord::Base)
65
- fail NameError
66
- end
67
- rescue NameError
68
- puts "Error: '#{@model}' is not an AR model"
69
- exit
70
- end
71
- end
72
- end
73
- end
@@ -1,34 +0,0 @@
1
- class <%= @controller_name -%> < <%= @base_controller %>
2
- include SimpleJsonApi::Helper
3
-
4
- def index
5
- @<%= class_name.underscore.gsub('/', '__').pluralize %> = <%= @model -%>.paginate(page: params[:page], per_page: params[:per_page]).to_a
6
- render json: SimpleJsonApi.render(
7
- model: @<%= class_name.underscore.gsub('/', '__').pluralize %>,
8
- serializer: <%= @serializer_name %>,
9
- fields: options_hash.fetch(:fields, nil),
10
- include: options_hash.fetch(:include, nil)
11
- ),
12
- status: 200
13
- end
14
-
15
- def show
16
- @<%= class_name.underscore.gsub('/', '__') %> = <%= @model -%>.find(params[:id])
17
- render json: SimpleJsonApi.render(
18
- model: @<%= class_name.underscore.gsub('/', '__') %>,
19
- serializer: <%= @serializer_name %>,
20
- fields: options_hash.fetch(:fields, nil),
21
- include: options_hash.fetch(:include, nil)
22
- ),
23
- status: 200
24
- end
25
-
26
- private
27
-
28
- def options_hash
29
- {
30
- fields: params[:fields],
31
- include: params[:include]
32
- }
33
- end
34
- end
@@ -1,14 +0,0 @@
1
- class <%= @serializer_name -%> < SimpleJsonApi::ResourceSerializer
2
- serializes :<%= class_name.underscore.gsub('/', '__').pluralize %>, model: <%= "::#{@model}" -%>, primary_key: :<%= @model.constantize.primary_key %>
3
-
4
- <%- @model.constantize.column_names.each do |col| -%>
5
- attribute :<%= col %>
6
- <%- end -%>
7
-
8
- <%- @model.constantize.reflect_on_all_associations.each do |assoc| -%>
9
- <%- klass_name = assoc.options[:class_name] -%>
10
- <%- serializer = [@namespace, klass_name].compact.join('::') + 'Serializer' if klass_name -%>
11
- <%= assoc.macro %> :<%= assoc.name %><%= ', polymorphic: true' if assoc.options[:polymorphic] %><%= ', serializer: ' + serializer if serializer %>
12
- <%- end -%>
13
- end
14
-
@@ -1,31 +0,0 @@
1
- require 'test_helper'
2
- require 'rails/generators'
3
- require 'rails/generators/test_case'
4
- require 'generators/simple_json_api/resource/resource_generator'
5
-
6
- module SimpleJsonApi
7
- module Generators
8
- # Tests the generation of the resource template files
9
- class ResourceGeneratorTest < Rails::Generators::TestCase
10
- tests ResourceGenerator
11
- destination 'tmp/generators'
12
- setup :prepare_destination
13
-
14
- def test_generator_runs
15
- # No error raised? It passes.
16
- run_generator %w(Project --namespace=Api::V3)
17
- end
18
-
19
- def test_bad_model
20
- assert_raises(SystemExit) do
21
- run_generator \
22
- %w(Project --namespace=Api::V3 --model=ProjectSerializer)
23
- end
24
- end
25
-
26
- def teardown
27
- FileUtils.rm_rf('tmp/generators')
28
- end
29
- end
30
- end
31
- end