jsonite 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 001f4ee4203a2a9ad449b3ce2be7bef23ba649dc
4
- data.tar.gz: cf3d345ce6b1e7194edf8a009512b5a5873f3972
3
+ metadata.gz: 5612be53563ec019fa0b12169f778105d529896c
4
+ data.tar.gz: f19a895e932ae5b559f5de7699c39df930189713
5
5
  SHA512:
6
- metadata.gz: c819dffe0197681f90b17d6e86b5e219861538830c966d2b6f23e3497018c70e09d3070147a618684bb661ed8a42ee95d3c41f01d7e5a9c7bb8854ece3176746
7
- data.tar.gz: 73ce6f0f49069b446b458347a3803d162b4bdd21d6ffd8ce74323d8e5e8a1f52b27a1a6d8b3c2a2e6d97c8496932d762dba5993bc332acf1fa1fc6b47e358b79
6
+ metadata.gz: 3273041c6a95535e89442a3d99ddf8bf6e2fe8dc3ce94d1a8e2c109a50f4b915a98ffc0ecefcfd42e3f026d7524993f9b3e9c1421b76bf0c8dc4c55e0af9c462
7
+ data.tar.gz: 461ea18c18c82ee91734e644cebfea19a733b2951a072ce39b4ca0244f7a1a3c2a9d1eca3657e7afb45a289ff1e7aa9c0accf6ddffe47ae0463b5065a0841db5
data/lib/jsonite.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'active_support/core_ext/object/blank'
2
2
  require 'active_support/json/encoding'
3
3
  require 'jsonite/helper'
4
+ require 'jsonite/lets_proxy'
4
5
 
5
6
  # = Jsonite
6
7
  #
@@ -23,29 +24,25 @@ class Jsonite
23
24
  # # => [{"email"=>"stephen@example.com"}, ...]
24
25
  #
25
26
  # Configuration options:
27
+ # * <tt>:root</tt> - A root key to wrap the resource with.
26
28
  # * <tt>:with</tt> - A specified presenter (defaults to `self`).
27
29
  #
28
- # All other options are passed along to <tt>#as_json</tt>.
30
+ # All other options are passed along to <tt>#present</tt>.
29
31
  def present resource, options = {}
30
32
  presenter = options.delete(:with) { self }
31
33
 
32
- case resource
33
- when Jsonite
34
- resource.as_json options
35
- else
36
- resource = if resource.respond_to?(:to_ary)
37
- resource.to_ary.map do |r|
38
- present presenter.new(r), options.merge(root: nil)
39
- end
40
- elsif resource.respond_to?(:as_json)
41
- present presenter.new(resource), options.merge(root: nil)
42
- else
43
- resource
34
+ presented = if resource.is_a? Jsonite
35
+ resource.present options
36
+ elsif resource.respond_to?(:to_ary)
37
+ resource.to_ary.map do |member|
38
+ presenter.new(member).present options.merge root: nil
44
39
  end
45
-
46
- root = options.fetch :root, Helper.resource_name(resource)
47
- root ? { root => resource } : resource
40
+ else
41
+ presenter.new(resource).present options.merge root: nil
48
42
  end
43
+
44
+ root = options.fetch(:root) { Helper.resource_name(resource) }
45
+ root ? { root => presented } : presented
49
46
  end
50
47
 
51
48
  # Defines a property to be exposed during presentation.
@@ -61,14 +58,9 @@ class Jsonite
61
58
  # * <tt>:with</tt> - A specified presenter. Ignored when a handler is
62
59
  # present. Useful when you want to embed a resource as a property (rather
63
60
  # than in the <tt>_embedded</tt> node).
61
+ # * <tt>:ignore_nil</tt> - Ignore `nil`.
64
62
  def property name, options = {}, &handler
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
63
+ properties[name.to_s] = { handler: handler }.merge options
72
64
  end
73
65
 
74
66
  def properties *properties
@@ -102,7 +94,7 @@ class Jsonite
102
94
  #
103
95
  # class UserPresenter < Jsonite
104
96
  # link :todos, title: 'To-dos', templated: true do |context|
105
- # "#{context.user_todos_url self}{?done}
97
+ # "#{context.user_todos_url self}{?done}"
106
98
  # end
107
99
  # end
108
100
  # # {
@@ -115,7 +107,7 @@ class Jsonite
115
107
  # # }
116
108
  # # }
117
109
  def link rel = :self, options = {}, &handler
118
- links[rel] = options.merge handler: Proc.new # enforce handler presence
110
+ links[rel.to_s] = { handler: Proc.new }.merge options # require handler
119
111
  end
120
112
 
121
113
  def links
@@ -143,27 +135,40 @@ class Jsonite
143
135
  # Configuration options:
144
136
  # * <tt>:with</tt> - A specified presenter. Required if a handler isn't
145
137
  # present.
138
+ # * <tt>:ignore_nil</tt> - Ignore `nil`.
146
139
  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
140
+ options.fetch :with unless handler
141
+ embedded[rel.to_s] = { handler: handler }.merge options
155
142
  end
156
143
 
157
144
  def embedded
158
145
  @embedded ||= {}
159
146
  end
160
147
 
148
+ # Defines a memoized "virtual" method on the resource.
149
+ #
150
+ # class UserPresenter < Jsonite
151
+ # let(:full_name) { "#{first_name} #{last_name}" }
152
+ # property :full_name
153
+ # end
154
+ # # {
155
+ # # "full_name": "Stephen Celis"
156
+ # # }
157
+ def let name, &handler
158
+ lets[name.to_s] = handler
159
+ end
160
+
161
+ def lets
162
+ @lets ||= {}
163
+ end
164
+
161
165
  private
162
166
 
163
167
  def inherited presenter
164
168
  presenter.properties.update properties
165
169
  presenter.links.update links
166
170
  presenter.embedded.update embedded
171
+ presenter.lets.update lets
167
172
  end
168
173
 
169
174
  end
@@ -177,49 +182,72 @@ class Jsonite
177
182
  @resource, @defaults = resource, defaults
178
183
  end
179
184
 
180
- # Returns a JSON representation (Hash) of the resource.
185
+ # Returns a raw representation (Hash) of the resource.
181
186
  #
182
187
  # Options:
183
188
  # * <tt>:context</tt> - A context to pass a presenter instance while
184
189
  # rendering properties, links, and embedded resources.
185
- def as_json options = {}
186
- return resource.as_json options if instance_of? Jsonite
190
+ def present options = {}
187
191
  options = defaults.merge options
192
+
188
193
  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
194
+ proxied = LetsProxy.new resource, context, self.class.lets
195
+
196
+ presented = properties proxied, context
197
+ _links = links proxied, context
198
+ presented['_links'] = _links if _links.present?
199
+ _embedded = embedded proxied, context
200
+ presented['_embedded'] = _embedded if _embedded.present?
201
+
202
+ root = options.fetch(:root) { Helper.resource_name(resource) }
203
+ root ? { root => presented } : presented
204
+ end
205
+
206
+ # Returns a JSON-ready representation (Hash) of the resource.
207
+ #
208
+ # Options:
209
+ # * <tt>:root</tt>
210
+ def as_json options = {}
211
+ present(options).as_json options
193
212
  end
194
213
 
195
214
  private
196
215
 
197
- def properties context = nil
198
- context ||= resource
199
- self.class.properties.each_with_object({}) do |(name, handler), props|
200
- catch :ignore do
201
- props[name] = resource.instance_exec context, &handler
202
- end
216
+ def properties rsrc, context = nil
217
+ self.class.properties.each_with_object({}) do |(name, options), props|
218
+ catch(:ignore) { props[name] = fetch name, rsrc, context, options }
203
219
  end
204
220
  end
205
221
 
206
- def links context = nil
207
- context ||= resource
222
+ def links rsrc, context = nil
208
223
  self.class.links.each_with_object({}) do |(rel, link), links|
209
224
  catch :ignore do
210
- href = resource.instance_exec context, &link[:handler]
211
- links[rel] = { href: href }.merge link.except :handler
225
+ href = fetch rel, rsrc, context, link
226
+ links[rel] = { 'href' => href }.merge link.except :handler
212
227
  end
213
228
  end
214
229
  end
215
230
 
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
221
- end
231
+ def embedded rsrc, context = nil
232
+ self.class.embedded.each_with_object({}) do |(name, options), embeds|
233
+ catch(:ignore) { embeds[name] = fetch name, rsrc, context, options }
234
+ end
235
+ end
236
+
237
+ def fetch name, rsrc, context, options
238
+ value = if options[:handler]
239
+ rsrc.instance_exec context, &options[:handler]
240
+ else
241
+ rsrc.__send__ name
222
242
  end
243
+
244
+ throw :ignore if options[:ignore_nil] && value.nil?
245
+
246
+ if options[:with] && !value.nil?
247
+ return options[:with].present value, context: context, root: nil
248
+ end
249
+
250
+ value
223
251
  end
224
252
 
225
253
  end
@@ -6,7 +6,7 @@ class Jsonite
6
6
  module_function
7
7
 
8
8
  def resource_name resource
9
- if resource.respond_to? :model_name
9
+ if resource.respond_to?(:model_name) && resource.respond_to?(:to_ary)
10
10
  resource.model_name.collection
11
11
  elsif resource.class.respond_to? :model_name
12
12
  resource.class.model_name.singular
@@ -0,0 +1,23 @@
1
+ class Jsonite
2
+ class LetsProxy < BasicObject
3
+
4
+ undef_method :==, :!, :!=
5
+
6
+ def initialize object, context, lets = {}
7
+ @__object__, @__context__, @__lets__ = object, context, lets
8
+
9
+ @__memoized__ = ::Hash.new do |memoized, name|
10
+ memoized[name] = instance_exec @__context__, &@__lets__.fetch(name)
11
+ end
12
+ end
13
+
14
+ def method_missing name, *args, &block
15
+ if @__lets__.key?(name.to_s)
16
+ @__memoized__[name.to_s]
17
+ else
18
+ @__object__.__send__ name, *args, &block
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  class Jsonite
2
2
 
3
- VERSION = '0.0.2'
3
+ VERSION = '0.0.3'
4
4
 
5
5
  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.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Celis
@@ -9,20 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-02 00:00:00.000000000 Z
12
+ date: 2015-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: 3.1.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - '>='
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 3.1.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: activemodel
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 3.1.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
26
40
  - !ruby/object:Gem::Version
27
41
  version: 3.1.0
28
42
  - !ruby/object:Gem::Dependency
@@ -61,9 +75,10 @@ executables: []
61
75
  extensions: []
62
76
  extra_rdoc_files: []
63
77
  files:
78
+ - lib/jsonite.rb
64
79
  - lib/jsonite/helper.rb
80
+ - lib/jsonite/lets_proxy.rb
65
81
  - lib/jsonite/version.rb
66
- - lib/jsonite.rb
67
82
  homepage: https://github.com/barrelage/jsonite
68
83
  licenses:
69
84
  - MIT
@@ -74,18 +89,19 @@ require_paths:
74
89
  - lib
75
90
  required_ruby_version: !ruby/object:Gem::Requirement
76
91
  requirements:
77
- - - '>='
92
+ - - ">="
78
93
  - !ruby/object:Gem::Version
79
94
  version: 1.9.3
80
95
  required_rubygems_version: !ruby/object:Gem::Requirement
81
96
  requirements:
82
- - - '>='
97
+ - - ">="
83
98
  - !ruby/object:Gem::Version
84
99
  version: '0'
85
100
  requirements: []
86
101
  rubyforge_project:
87
- rubygems_version: 2.0.2
102
+ rubygems_version: 2.2.2
88
103
  signing_key:
89
104
  specification_version: 4
90
105
  summary: A tiny, HAL-compliant JSON presenter
91
106
  test_files: []
107
+ has_rdoc: false