granola-schema 0.0.4 → 0.9.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.
- checksums.yaml +4 -4
- data/README.md +79 -14
- data/lib/granola/schema.rb +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 361ab0951c367d4e574849c14618f3706d0b3ee7
|
4
|
+
data.tar.gz: 6c925857257d586bcd8abaf6a83ac147cb7711cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45260d91c3143723a6a52063a1ba3bde5360eac45740951675943a5aaae695637a918f0152ef56fbf67e3c658c0ed963218b6cba3d1882819bc5c24703a51f71
|
7
|
+
data.tar.gz: a38320a37f9f50c9dfb13c386279ed58febf997d5124a13773de94ec782a6c269405b098ecafb42b88736897db5ee3fafbd1d6d585a3aa7f153262b2ddb48207
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Granola, a JSON serializer
|
1
|
+
# Granola, a JSON serializer [](https://travis-ci.org/foca/granola)
|
2
2
|
|
3
3
|

|
4
4
|
|
@@ -11,7 +11,7 @@ gets out of your way. You just write plain ruby.
|
|
11
11
|
|
12
12
|
``` ruby
|
13
13
|
class PersonSerializer < Granola::Serializer
|
14
|
-
def
|
14
|
+
def serialized
|
15
15
|
{
|
16
16
|
"name" => object.name,
|
17
17
|
"email" => object.email,
|
@@ -34,10 +34,14 @@ specific JSON backend. It defaults to the native JSON backend, but you're free
|
|
34
34
|
to change it. For example, if you were using [Yajl][]:
|
35
35
|
|
36
36
|
``` ruby
|
37
|
-
Granola.json =
|
37
|
+
Granola.json = Yajl::Encoder.method(:encode)
|
38
38
|
```
|
39
39
|
|
40
|
+
If your project already uses [MultiJson][] then we will default to whatever it's
|
41
|
+
using, so you shouldn't worry.
|
42
|
+
|
40
43
|
[Yajl]: https://github.com/brianmario/yajl-ruby
|
44
|
+
[MultiJson]: https://github.com/intridea/multi_json
|
41
45
|
|
42
46
|
## Handling lists of models
|
43
47
|
|
@@ -55,8 +59,8 @@ If your application is based on Rack, you can simply `include Granola::Rack` and
|
|
55
59
|
you get access to the following interface:
|
56
60
|
|
57
61
|
``` ruby
|
58
|
-
|
59
|
-
|
62
|
+
granola(person) #=> This will infer PersonSerializer from a Person instance
|
63
|
+
granola(person, with: AnotherSerializer)
|
60
64
|
```
|
61
65
|
|
62
66
|
*NOTE* The method relies on being an `env` method that returns the Rack
|
@@ -72,7 +76,7 @@ Cuba.plugin Granola::Rack
|
|
72
76
|
Cuba.define do
|
73
77
|
on get, "users/:id" do |id|
|
74
78
|
user = User[id]
|
75
|
-
halt
|
79
|
+
halt granola(user)
|
76
80
|
end
|
77
81
|
end
|
78
82
|
```
|
@@ -81,16 +85,77 @@ end
|
|
81
85
|
|
82
86
|
## Caching
|
83
87
|
|
84
|
-
`Granola::Serializer` gives you
|
85
|
-
serializers
|
86
|
-
|
88
|
+
`Granola::Serializer` gives you two methods that you can implement in your
|
89
|
+
serializers: `last_modified` and `cache_key`.
|
90
|
+
|
91
|
+
When using the `Granola::Rack` module, you should return a `Time` object from
|
92
|
+
your serializer's `last_modified`. Granola will use this to generate the
|
93
|
+
appropriate `Last-Modified` HTTP header. Likewise, the result of `cache_key`
|
94
|
+
will be MD5d and set as the response's `ETag` header.
|
95
|
+
|
96
|
+
If you do this, you should also make sure that the [`Rack::ConditionalGet`][cg]
|
97
|
+
middleware is in your Rack stack, as it will use these headers to avoid
|
98
|
+
generating the JSON response altogether. For example, using Cuba:
|
99
|
+
|
100
|
+
``` ruby
|
101
|
+
class UserSerializer < Granola::Serializer
|
102
|
+
def serialized
|
103
|
+
{ "id" => object.id, "name" => object.name, "email" => object.email }
|
104
|
+
end
|
105
|
+
|
106
|
+
def last_modified
|
107
|
+
object.updated_at
|
108
|
+
end
|
109
|
+
|
110
|
+
def cache_key
|
111
|
+
"user:#{object.id}:#{object.updated_at.to_i}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
Cuba.plugin Granola::Rack
|
116
|
+
Cuba.use Rack::ConditionalGet
|
117
|
+
|
118
|
+
Cuba.define do
|
119
|
+
on get, "users/:id" do |id|
|
120
|
+
halt granola(User[id])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
This will avoid generating the JSON response altogether if the user sends the
|
126
|
+
appropriate `If-Modified-Since` or `If-None-Match` headers.
|
127
|
+
|
128
|
+
[cg]: http://www.rubydoc.info/github/rack/rack/Rack/ConditionalGet
|
129
|
+
|
130
|
+
## Different Formats
|
131
|
+
|
132
|
+
Although Granola out of the box only ships with JSON serialization support, it's
|
133
|
+
easy to extend and add support for different types of serialization in case your
|
134
|
+
API needs to provide multiple formats. For example, in order to add MsgPack
|
135
|
+
support (via the [msgpack-ruby][] library), you'd do this:
|
136
|
+
|
137
|
+
``` ruby
|
138
|
+
require "msgpack"
|
139
|
+
|
140
|
+
class BaseSerializer < Granola::Serializer
|
141
|
+
MIME_TYPES[:msgpack] = "application/x-msgpack".freeze
|
142
|
+
|
143
|
+
def to_msgpack(*)
|
144
|
+
MsgPack.pack(serialized)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
Now all serializers that inherit from `BaseSerializer` can be serialized into
|
150
|
+
MsgPack. In order to use this from our Rack helpers, you'd do:
|
151
|
+
|
152
|
+
``` ruby
|
153
|
+
granola(object, as: :msgpack)
|
154
|
+
```
|
87
155
|
|
88
|
-
|
89
|
-
`If-Modified-Since` or `If-None-Match` headers, the helper will automatically
|
90
|
-
return a 304 response.
|
156
|
+
This will set the correct MIME type.
|
91
157
|
|
92
|
-
|
93
|
-
hitting the endpoint altogether.
|
158
|
+
[msgpack-ruby]: https://github.com/msgpack/msgpack-ruby
|
94
159
|
|
95
160
|
## License
|
96
161
|
|
data/lib/granola/schema.rb
CHANGED
@@ -26,7 +26,7 @@ module Granola
|
|
26
26
|
def valid?
|
27
27
|
validation_errors.clear
|
28
28
|
validation_errors.concat(
|
29
|
-
JSON::Validator.fully_validate(self.class.schema,
|
29
|
+
JSON::Validator.fully_validate(self.class.schema, serialized)
|
30
30
|
)
|
31
31
|
validation_errors.empty?
|
32
32
|
end
|
@@ -52,7 +52,7 @@ module Granola
|
|
52
52
|
# serializer = SchemaSerializer.new(PersonSerializer.schema)
|
53
53
|
# serializer.to_json
|
54
54
|
class SchemaSerializer < Serializer
|
55
|
-
def
|
55
|
+
def serialized
|
56
56
|
{
|
57
57
|
"$schema".freeze => "http://json-schema.org/schema#".freeze,
|
58
58
|
"type".freeze => "object".freeze
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: granola-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Sanguinetti
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: granola
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0
|
19
|
+
version: 0.9.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0
|
26
|
+
version: 0.9.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json-schema
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|