jsonite 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jsonite/version.rb +1 -1
  3. data/lib/jsonite.rb +147 -21
  4. metadata +34 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49c0a11e4a44bd3ab0ad87f0cbf27debc56afd10
4
- data.tar.gz: beeb10b2cc59a4e812c492cfba50bce34dfe5b4c
3
+ metadata.gz: 001f4ee4203a2a9ad449b3ce2be7bef23ba649dc
4
+ data.tar.gz: cf3d345ce6b1e7194edf8a009512b5a5873f3972
5
5
  SHA512:
6
- metadata.gz: bee8032685d34443435ef821aaa94b8fe0b4170ecc6e0a1fb55b6ed1bb1ae95346f8b50dce5f22c57d3673f1f7027b881291c5e9199f08bd12fbcdd5797a4321
7
- data.tar.gz: b3d8f45e00dd6164f2655988bbe6a5e2bc8880cde5ec1d9773087edc8518f047c07b2f8982e184d600c400d30ec847e0a2c05f29f3cb0fb54acfdf1fde65fe7b
6
+ metadata.gz: c819dffe0197681f90b17d6e86b5e219861538830c966d2b6f23e3497018c70e09d3070147a618684bb661ed8a42ee95d3c41f01d7e5a9c7bb8854ece3176746
7
+ data.tar.gz: 73ce6f0f49069b446b458347a3803d162b4bdd21d6ffd8ce74323d8e5e8a1f52b27a1a6d8b3c2a2e6d97c8496932d762dba5993bc332acf1fa1fc6b47e358b79
@@ -1,5 +1,5 @@
1
1
  class Jsonite
2
2
 
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
 
5
5
  end
data/lib/jsonite.rb CHANGED
@@ -1,14 +1,33 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'active_support/json/encoding'
1
3
  require 'jsonite/helper'
2
4
 
3
- # A simple JSON presenter for hypermedia applications.
4
- # Loosely adheers to HAL: http://stateless.co/hal_specification.html
5
-
5
+ # = Jsonite
6
+ #
7
+ # A tiny, HAL-compliant JSON presenter.
8
+ #
9
+ # http://tools.ietf.org/html/draft-kelly-json-hal-05
6
10
  class Jsonite
7
11
 
8
12
  class << self
9
13
 
14
+ # Presents a resource (or array of resources).
15
+ #
16
+ # class UserPresenter < Jsonite
17
+ # property :email
18
+ # end
19
+ # users = User.all
20
+ # UserPresenter.present(users.first)
21
+ # # => {"email"=>"stephen@example.com"}
22
+ # UserPresenter.present(users)
23
+ # # => [{"email"=>"stephen@example.com"}, ...]
24
+ #
25
+ # Configuration options:
26
+ # * <tt>:with</tt> - A specified presenter (defaults to `self`).
27
+ #
28
+ # All other options are passed along to <tt>#as_json</tt>.
10
29
  def present resource, options = {}
11
- presenter = options.fetch :with, self
30
+ presenter = options.delete(:with) { self }
12
31
 
13
32
  case resource
14
33
  when Jsonite
@@ -29,8 +48,27 @@ class Jsonite
29
48
  end
30
49
  end
31
50
 
51
+ # Defines a property to be exposed during presentation.
52
+ #
53
+ # class UserPresenter < Jsonite
54
+ # property :email
55
+ # end
56
+ # # {
57
+ # # "email": "stephen@example.com"
58
+ # # }
59
+ #
60
+ # Configuration options:
61
+ # * <tt>:with</tt> - A specified presenter. Ignored when a handler is
62
+ # present. Useful when you want to embed a resource as a property (rather
63
+ # than in the <tt>_embedded</tt> node).
32
64
  def property name, options = {}, &handler
33
- properties[name] = handler || proc { send name }
65
+ handler ||= if options[:with]
66
+ proc { Jsonite.present send(name), with: options[:with] }
67
+ else
68
+ proc { send name }
69
+ end
70
+
71
+ properties[name] = handler
34
72
  end
35
73
 
36
74
  def properties *properties
@@ -39,44 +77,123 @@ class Jsonite
39
77
  @properties
40
78
  end
41
79
 
42
- def embedded name, options = {}, &handler
43
- unless options[:with].is_a?(Class) && options[:with] <= Jsonite
44
- raise KeyError, ':with option must be a Jsonite'
45
- end
46
-
47
- property name, options do |context|
48
- resource = handler ? instance_exec(context, &handler) : send(name)
49
- present resource, { context: context, root: nil }.merge(options)
50
- end
51
- end
52
-
80
+ # Defines a link.
81
+ #
82
+ # class UserPresenter < Jsonite
83
+ # link do |context|
84
+ # context.user_url self
85
+ # end
86
+ # link :todos do |context|
87
+ # context.user_todos_url self
88
+ # end
89
+ # end
90
+ # # {
91
+ # # "_links": {
92
+ # # "self": {
93
+ # # "href": "http://example.com/users/8oljbpyjetu8"
94
+ # # },
95
+ # # "todos": {
96
+ # # "href": "http://example.com/users/8oljbpyjetu8/todos"
97
+ # # }
98
+ # # }
99
+ # # }
100
+ #
101
+ # Configuration options are displayed as additional properties on a link.
102
+ #
103
+ # class UserPresenter < Jsonite
104
+ # link :todos, title: 'To-dos', templated: true do |context|
105
+ # "#{context.user_todos_url self}{?done}
106
+ # end
107
+ # end
108
+ # # {
109
+ # # "_links": {
110
+ # # "todos": {
111
+ # # "href": "http://example.com/users/8oljbpyjetu8/todos{?done}",
112
+ # # "title": "To-dos",
113
+ # # "templated": true
114
+ # # }
115
+ # # }
116
+ # # }
53
117
  def link rel = :self, options = {}, &handler
54
- links[rel] = options.merge handler: handler
118
+ links[rel] = options.merge handler: Proc.new # enforce handler presence
55
119
  end
56
120
 
57
121
  def links
58
122
  @links ||= {}
59
123
  end
60
124
 
125
+ # Defines an embedded resource.
126
+ #
127
+ # class TodoPresenter < Jsonite
128
+ # property :description
129
+ # end
130
+ # class UserPresenter < Jsonite
131
+ # embed :todos, with: TodoPresenter
132
+ # end
133
+ # # {
134
+ # # "_embedded": {
135
+ # # "todos": [
136
+ # # {
137
+ # # "description": "Buy milk"
138
+ # # }
139
+ # # ]
140
+ # # }
141
+ # # }
142
+ #
143
+ # Configuration options:
144
+ # * <tt>:with</tt> - A specified presenter. Required if a handler isn't
145
+ # present.
146
+ def embed rel, options = {}, &handler
147
+ if handler.nil?
148
+ presenter = options.fetch :with
149
+ handler = proc do |context|
150
+ Jsonite.present send(rel), with: presenter, context: context
151
+ end
152
+ end
153
+
154
+ embedded[rel] = handler
155
+ end
156
+
157
+ def embedded
158
+ @embedded ||= {}
159
+ end
160
+
161
+ private
162
+
61
163
  def inherited presenter
62
164
  presenter.properties.update properties
63
165
  presenter.links.update links
166
+ presenter.embedded.update embedded
64
167
  end
65
168
 
66
169
  end
67
170
 
68
171
  attr_reader :resource, :defaults
69
172
 
173
+ # Initializes a new presenter instance with the given resource.
174
+ #
175
+ # Default options are passed to #as_json during presentation.
70
176
  def initialize resource, defaults = {}
71
177
  @resource, @defaults = resource, defaults
72
178
  end
73
179
 
180
+ # Returns a JSON representation (Hash) of the resource.
181
+ #
182
+ # Options:
183
+ # * <tt>:context</tt> - A context to pass a presenter instance while
184
+ # rendering properties, links, and embedded resources.
74
185
  def as_json options = {}
75
186
  return resource.as_json options if instance_of? Jsonite
76
- context, options = options.delete(:context), defaults.merge(options)
77
- properties(context).merge(_links: links(context)).as_json options
187
+ options = defaults.merge options
188
+ context = options.delete :context
189
+ hash = properties context
190
+ hash.update _links: links(context) if self.class.links.present?
191
+ hash.update _embedded: embedded(context) if self.class.embedded.present?
192
+ hash.as_json options
78
193
  end
79
194
 
195
+ private
196
+
80
197
  def properties context = nil
81
198
  context ||= resource
82
199
  self.class.properties.each_with_object({}) do |(name, handler), props|
@@ -88,10 +205,19 @@ class Jsonite
88
205
 
89
206
  def links context = nil
90
207
  context ||= resource
91
- self.class.links.each_with_object({}) do |(name, link), props|
208
+ self.class.links.each_with_object({}) do |(rel, link), links|
92
209
  catch :ignore do
93
210
  href = resource.instance_exec context, &link[:handler]
94
- props[name] = { href: href }.merge link.except :handler
211
+ links[rel] = { href: href }.merge link.except :handler
212
+ end
213
+ end
214
+ end
215
+
216
+ def embedded context = nil
217
+ context ||= resource
218
+ self.class.embedded.each_with_object({}) do |(name, handler), embedded|
219
+ catch :ignore do
220
+ embedded[name] = resource.instance_exec context, &handler
95
221
  end
96
222
  end
97
223
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Celis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-31 00:00:00.000000000 Z
12
+ date: 2013-08-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -25,7 +25,35 @@ dependencies:
25
25
  - - '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: 3.1.0
28
- description: Tiny JSON presenter
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '='
33
+ - !ruby/object:Gem::Version
34
+ version: 10.1.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '='
40
+ - !ruby/object:Gem::Version
41
+ version: 10.1.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '='
47
+ - !ruby/object:Gem::Version
48
+ version: 2.14.1
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 2.14.1
56
+ description: Jsonite provides a very simple DSL to build HAL-compliant JSON presenters.
29
57
  email:
30
58
  - stephen@stephencelis.com
31
59
  - kainosnoema@gmail.com
@@ -37,7 +65,8 @@ files:
37
65
  - lib/jsonite/version.rb
38
66
  - lib/jsonite.rb
39
67
  homepage: https://github.com/barrelage/jsonite
40
- licenses: []
68
+ licenses:
69
+ - MIT
41
70
  metadata: {}
42
71
  post_install_message:
43
72
  rdoc_options: []
@@ -58,5 +87,5 @@ rubyforge_project:
58
87
  rubygems_version: 2.0.2
59
88
  signing_key:
60
89
  specification_version: 4
61
- summary: Tiny JSON presenter
90
+ summary: A tiny, HAL-compliant JSON presenter
62
91
  test_files: []