rep 0.1.1 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rep.rb CHANGED
@@ -25,6 +25,7 @@ require 'forwardable'
25
25
  # `JSON::generate` and `JSON::decode` are much safer to use than `Object#to_json`.
26
26
 
27
27
  require 'json'
28
+ require 'mashed'
28
29
 
29
30
  require 'rep/version'
30
31
  module Rep
@@ -46,10 +47,6 @@ module Rep
46
47
  alias fields json_fields
47
48
  end
48
49
  end
49
-
50
- if defined?(Mashed)
51
- include MashedSupport
52
- end
53
50
  }
54
51
  end
55
52
 
@@ -75,21 +72,24 @@ module Rep
75
72
 
76
73
  def to_hash(name = :default)
77
74
  if fields = self.class.json_fields(name)
78
- fields.reduce({}) do |memo, field|
75
+ fields.each_with_object({}) do |field, memo|
79
76
  field_name, method_name = field.is_a?(Hash) ? field.to_a.first : [field, field]
80
- begin
77
+ if self.respond_to?(method_name)
81
78
  memo[field_name] = send(method_name)
82
- rescue NoMethodError => e
79
+ else
83
80
  message = "There is no method named '#{method_name}' for the class '#{self.class}' for the '#{name}' list of fields : #{e.message}"
84
81
  raise NoMethodError.new(message, method_name, e.args)
85
82
  end
86
- memo
87
83
  end
88
84
  else
89
85
  raise "There are no json fields under the name: #{name}"
90
86
  end
91
87
  end
92
88
 
89
+ def to_mash(name = :default)
90
+ Mashed::Mash.new(to_hash(name))
91
+ end
92
+
93
93
  def to_json
94
94
  JSON.generate(to_hash)
95
95
  end
@@ -299,10 +299,4 @@ module Rep
299
299
  }
300
300
  end
301
301
  end
302
-
303
- module MashedSupport
304
- def to_hash(name = :default)
305
- Mashed::Mash.new(super)
306
- end
307
- end
308
302
  end
data/lib/rep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rep
2
- VERSION = "0.1.1"
2
+ VERSION = "0.9.1"
3
3
  end
data/rep.gemspec CHANGED
@@ -16,8 +16,9 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'mashed', '>= 0.9.0'
21
+
19
22
  gem.add_development_dependency 'rake'
20
23
  gem.add_development_dependency 'minitest'
21
- gem.add_development_dependency 'rocco'
22
- gem.add_development_dependency 'rdiscount'
23
24
  end
metadata CHANGED
@@ -1,45 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - myobie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-31 00:00:00.000000000 Z
11
+ date: 2014-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: minitest
14
+ name: mashed
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - '>='
32
18
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
19
+ version: 0.9.0
20
+ type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
24
  - - '>='
39
25
  - !ruby/object:Gem::Version
40
- version: '0'
26
+ version: 0.9.0
41
27
  - !ruby/object:Gem::Dependency
42
- name: rocco
28
+ name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - '>='
@@ -53,7 +39,7 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: rdiscount
42
+ name: minitest
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - '>='
@@ -80,11 +66,19 @@ files:
80
66
  - LICENSE.txt
81
67
  - README.md
82
68
  - Rakefile
69
+ - docs/docco.css
83
70
  - docs/index.html
84
- - docs/lib/rep.html
85
- - docs/lib/rep/version.html
71
+ - docs/public/fonts/aller-bold.eot
72
+ - docs/public/fonts/aller-bold.ttf
73
+ - docs/public/fonts/aller-bold.woff
74
+ - docs/public/fonts/aller-light.eot
75
+ - docs/public/fonts/aller-light.ttf
76
+ - docs/public/fonts/aller-light.woff
77
+ - docs/public/fonts/novecento-bold.eot
78
+ - docs/public/fonts/novecento-bold.ttf
79
+ - docs/public/fonts/novecento-bold.woff
80
+ - docs/public/stylesheets/normalize.css
86
81
  - docs/rep.html
87
- - docs/rep/version.html
88
82
  - lib/rep.rb
89
83
  - lib/rep/version.rb
90
84
  - rep.gemspec
@@ -109,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
103
  version: '0'
110
104
  requirements: []
111
105
  rubyforge_project:
112
- rubygems_version: 2.0.3
106
+ rubygems_version: 2.0.2
113
107
  signing_key:
114
108
  specification_version: 4
115
109
  summary: Include Rep into any object to endow it to create json (or hashes) easily.
data/docs/lib/rep.html DELETED
@@ -1,484 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
- <title>rep.rb</title>
6
- <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
- </head>
8
- <body>
9
- <div id='container'>
10
- <div id="background"></div>
11
- <div id="jump_to">
12
- Jump To &hellip;
13
- <div id="jump_wrapper">
14
- <div id="jump_page">
15
- <a class="source" href="rep.html">rep.rb</a>
16
- <a class="source" href="rep/version.html">version.rb</a>
17
- </div>
18
- </div>
19
- </div>
20
- <table cellspacing=0 cellpadding=0>
21
- <thead>
22
- <tr>
23
- <th class=docs><h1>rep.rb</h1></th>
24
- <th class=code></th>
25
- </tr>
26
- </thead>
27
- <tbody>
28
- <tr id='section-1'>
29
- <td class=docs>
30
- <div class="pilwrap">
31
- <a class="pilcrow" href="#section-1">&#182;</a>
32
- </div>
33
- <p><strong>Rep</strong> is a small module to endow any class to make json quickly. It solves four problems:</p>
34
-
35
- <ol>
36
- <li>Enumerating top level keys for a json structure</li>
37
- <li>Providing a convention for the value of those keys</li>
38
- <li>Defining <code>attr_accessor</code>&rsquo;s that are prefilled from an options hash given to <code>#initialize</code></li>
39
- <li>Sharing instances to help GC</li>
40
- </ol>
41
-
42
-
43
- <p>The code is available on <a href="http://github.com/myobie/rep">github</a>.</p>
44
- </td>
45
- <td class=code>
46
- <div class='highlight'><pre></pre></div>
47
- </td>
48
- </tr>
49
- <tr id='section-2'>
50
- <td class=docs>
51
- <div class="pilwrap">
52
- <a class="pilcrow" href="#section-2">&#182;</a>
53
- </div>
54
- <p><code>Forwardable</code> is in the stdlib and allows ruby objects to delegate methods off to other objects. An example:</p>
55
-
56
- <pre><code>class A
57
- extend Forwardable
58
- delegate [:length, :first] =&gt; :@array
59
- def initialize(array = [])
60
- @array = array
61
- end
62
- end
63
-
64
- A.new([1,2,3]).length # =&gt; 3
65
- A.new([1,2,3]).first # =&gt; 1
66
- </code></pre>
67
- </td>
68
- <td class=code>
69
- <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;forwardable&#39;</span></pre></div>
70
- </td>
71
- </tr>
72
- <tr id='section-3'>
73
- <td class=docs>
74
- <div class="pilwrap">
75
- <a class="pilcrow" href="#section-3">&#182;</a>
76
- </div>
77
- <p><code>JSON::generate</code> and <code>JSON::decode</code> are much safer to use than <code>Object#to_json</code>.</p>
78
- </td>
79
- <td class=code>
80
- <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;json&#39;</span>
81
-
82
- <span class="nb">require</span> <span class="s1">&#39;rep/version&#39;</span>
83
- <span class="k">module</span> <span class="nn">Rep</span></pre></div>
84
- </td>
85
- </tr>
86
- <tr id='section-4'>
87
- <td class=docs>
88
- <div class="pilwrap">
89
- <a class="pilcrow" href="#section-4">&#182;</a>
90
- </div>
91
- <p>All classes that <code>include Rep</code> are extended with <code>Forwardable</code>,
92
- given some aliases, endowned with <code>HashieSupport</code> if Hashie is loaded,
93
- and given a delegate method if it doesn&rsquo;t already have one.</p>
94
- </td>
95
- <td class=code>
96
- <div class='highlight'><pre> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">included</span><span class="p">(</span><span class="n">klass</span><span class="p">)</span>
97
- <span class="n">klass</span><span class="o">.</span><span class="n">extend</span> <span class="no">Forwardable</span>
98
- <span class="n">klass</span><span class="o">.</span><span class="n">extend</span> <span class="no">ClassMethods</span>
99
- <span class="n">klass</span><span class="o">.</span><span class="n">instance_eval</span> <span class="p">{</span>
100
- <span class="k">class</span> <span class="o">&lt;&lt;</span> <span class="nb">self</span>
101
- <span class="k">unless</span> <span class="n">defined?</span><span class="p">(</span><span class="n">forward</span><span class="p">)</span>
102
- <span class="k">alias</span> <span class="n">forward</span> <span class="n">delegate</span>
103
- <span class="k">end</span>
104
-
105
- <span class="k">unless</span> <span class="n">defined?</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span>
106
- <span class="k">alias</span> <span class="n">fields</span> <span class="n">json_fields</span>
107
- <span class="k">end</span>
108
- <span class="k">end</span>
109
-
110
- <span class="k">if</span> <span class="n">defined?</span><span class="p">(</span><span class="no">Mashed</span><span class="p">)</span>
111
- <span class="kp">include</span> <span class="no">MashedSupport</span>
112
- <span class="k">end</span>
113
- <span class="p">}</span>
114
- <span class="k">end</span></pre></div>
115
- </td>
116
- </tr>
117
- <tr id='section-5'>
118
- <td class=docs>
119
- <div class="pilwrap">
120
- <a class="pilcrow" href="#section-5">&#182;</a>
121
- </div>
122
- <p>Since a goal is to be able to share instances, we need an easy way to reset a
123
- shared instance back to factory defaults. If you memoize any methods that are
124
- not declared as json fields, then overried this method and set any memoized
125
- variables to nil, then super.</p>
126
- </td>
127
- <td class=code>
128
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">reset_for_json!</span>
129
- <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">all_json_methods</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">method_name</span><span class="o">|</span>
130
- <span class="nb">instance_variable_set</span><span class="p">(</span><span class="ss">:&quot;@</span><span class="si">#{</span><span class="n">method_name</span><span class="si">}</span><span class="ss">&quot;</span><span class="p">,</span> <span class="kp">nil</span><span class="p">)</span>
131
- <span class="k">end</span>
132
- <span class="k">end</span></pre></div>
133
- </td>
134
- </tr>
135
- <tr id='section-6'>
136
- <td class=docs>
137
- <div class="pilwrap">
138
- <a class="pilcrow" href="#section-6">&#182;</a>
139
- </div>
140
- <p>All the work of generating a hash from an instance is packaged up in one method. Since
141
- fields can be aliases in the format <code>{ :json_key_name =&gt; :method_name }</code>, there
142
- is some fancy logic to determine the <code>field_name</code> and <code>method_name</code> variables.</p>
143
-
144
- <pre><code>{ :one =&gt; :foo }.to_a # =&gt; [[:one, :foo]]
145
- </code></pre>
146
-
147
- <p>Right now it will raise if either a field doesn&rsquo;t have a method to provide it&rsquo;s value or
148
- if there are no json fields setup for the particular set (which defaults to <code>:default</code>).</p>
149
- </td>
150
- <td class=code>
151
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">to_hash</span><span class="p">(</span><span class="nb">name</span> <span class="o">=</span> <span class="ss">:default</span><span class="p">)</span>
152
- <span class="k">if</span> <span class="n">fields</span> <span class="o">=</span> <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">json_fields</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
153
- <span class="n">fields</span><span class="o">.</span><span class="n">reduce</span><span class="p">({})</span> <span class="k">do</span> <span class="o">|</span><span class="n">memo</span><span class="p">,</span> <span class="n">field</span><span class="o">|</span>
154
- <span class="n">field_name</span><span class="p">,</span> <span class="n">method_name</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span> <span class="p">:</span> <span class="o">[</span><span class="n">field</span><span class="p">,</span> <span class="n">field</span><span class="o">]</span>
155
- <span class="k">begin</span>
156
- <span class="n">memo</span><span class="o">[</span><span class="n">field_name</span><span class="o">]</span> <span class="o">=</span> <span class="nb">send</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span>
157
- <span class="k">rescue</span> <span class="no">NoMethodError</span> <span class="o">=&gt;</span> <span class="n">e</span>
158
- <span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;There is no method named &#39;</span><span class="si">#{</span><span class="n">method_name</span><span class="si">}</span><span class="s2">&#39; for the class &#39;</span><span class="si">#{</span><span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="si">}</span><span class="s2">&#39; for the &#39;</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">&#39; list of fields : </span><span class="si">#{</span><span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="si">}</span><span class="s2">&quot;</span>
159
- <span class="k">raise</span> <span class="no">NoMethodError</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">method_name</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
160
- <span class="k">end</span>
161
- <span class="n">memo</span>
162
- <span class="k">end</span>
163
- <span class="k">else</span>
164
- <span class="k">raise</span> <span class="s2">&quot;There are no json fields under the name: </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">&quot;</span>
165
- <span class="k">end</span>
166
- <span class="k">end</span>
167
-
168
- <span class="k">def</span> <span class="nf">to_json</span>
169
- <span class="no">JSON</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">to_hash</span><span class="p">)</span>
170
- <span class="k">end</span>
171
-
172
- <span class="k">module</span> <span class="nn">ClassMethods</span></pre></div>
173
- </td>
174
- </tr>
175
- <tr id='section-7'>
176
- <td class=docs>
177
- <div class="pilwrap">
178
- <a class="pilcrow" href="#section-7">&#182;</a>
179
- </div>
180
- <p>Defines an attr_accessor with a default value. The default for default is nil. Example:</p>
181
-
182
- <pre><code>class A
183
- register_accessor :name =&gt; "No Name"
184
- end
185
-
186
- A.new.name # =&gt; "No Name"
187
- </code></pre>
188
- </td>
189
- <td class=code>
190
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">register_accessor</span><span class="p">(</span><span class="n">acc</span><span class="p">)</span>
191
- <span class="nb">name</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">acc</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">acc</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span> <span class="p">:</span> <span class="o">[</span><span class="n">acc</span><span class="p">,</span> <span class="kp">nil</span><span class="o">]</span>
192
- <span class="kp">attr_accessor</span> <span class="nb">name</span>
193
- <span class="k">if</span> <span class="n">default</span>
194
- <span class="n">define_method</span> <span class="nb">name</span> <span class="k">do</span>
195
- <span class="n">var_name</span> <span class="o">=</span> <span class="ss">:&quot;@</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="ss">&quot;</span>
196
- <span class="nb">instance_variable_get</span><span class="p">(</span><span class="n">var_name</span><span class="p">)</span> <span class="o">||</span> <span class="nb">instance_variable_set</span><span class="p">(</span><span class="n">var_name</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
197
- <span class="k">end</span>
198
- <span class="k">end</span>
199
- <span class="k">end</span></pre></div>
200
- </td>
201
- </tr>
202
- <tr id='section-8'>
203
- <td class=docs>
204
- <div class="pilwrap">
205
- <a class="pilcrow" href="#section-8">&#182;</a>
206
- </div>
207
- <p>Defines an <code>#initialize</code> method that accepts a Hash argument and copies some keys out into <code>attr_accessors</code>.
208
- If your class already has an <code>#iniatialize</code> method then this will overwrite it (so don&rsquo;t use it). <code>#initialize_with</code>
209
- does not have to be used to use any other parts of Rep.</p>
210
- </td>
211
- <td class=code>
212
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">initialize_with</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
213
- <span class="vi">@initializiation_args</span> <span class="o">=</span> <span class="n">args</span></pre></div>
214
- </td>
215
- </tr>
216
- <tr id='section-9'>
217
- <td class=docs>
218
- <div class="pilwrap">
219
- <a class="pilcrow" href="#section-9">&#182;</a>
220
- </div>
221
- <p>Remember what args we normally initialize with so we can refer to them when building shared instances.</p>
222
- </td>
223
- <td class=code>
224
- <div class='highlight'><pre> <span class="k">if</span> <span class="n">defined?</span><span class="p">(</span><span class="n">define_singleton_method</span><span class="p">)</span>
225
- <span class="n">define_singleton_method</span> <span class="ss">:initializiation_args</span> <span class="k">do</span>
226
- <span class="vi">@initializiation_args</span>
227
- <span class="k">end</span>
228
- <span class="k">else</span>
229
- <span class="n">singleton</span> <span class="o">=</span> <span class="k">class</span> <span class="o">&lt;&lt;</span> <span class="nb">self</span><span class="p">;</span> <span class="nb">self</span> <span class="k">end</span>
230
- <span class="n">singleton</span><span class="o">.</span><span class="n">send</span> <span class="ss">:define_method</span><span class="p">,</span> <span class="ss">:initializiation_args</span><span class="p">,</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="vi">@initializiation_args</span> <span class="p">}</span>
231
- <span class="k">end</span></pre></div>
232
- </td>
233
- </tr>
234
- <tr id='section-10'>
235
- <td class=docs>
236
- <div class="pilwrap">
237
- <a class="pilcrow" href="#section-10">&#182;</a>
238
- </div>
239
- <p>Create an <code>attr_accessor</code> for each one. Defaults can be provided using the Hash version { :arg => :default_value }</p>
240
- </td>
241
- <td class=code>
242
- <div class='highlight'><pre> <span class="n">args</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="o">|</span> <span class="n">register_accessor</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="p">}</span>
243
-
244
- <span class="n">define_method</span><span class="p">(</span><span class="ss">:initialize</span><span class="p">)</span> <span class="p">{</span> <span class="o">|*</span><span class="n">args</span><span class="o">|</span>
245
- <span class="n">opts</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">first</span> <span class="o">||</span> <span class="p">{}</span>
246
- <span class="n">parse_opts</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
247
- <span class="p">}</span></pre></div>
248
- </td>
249
- </tr>
250
- <tr id='section-11'>
251
- <td class=docs>
252
- <div class="pilwrap">
253
- <a class="pilcrow" href="#section-11">&#182;</a>
254
- </div>
255
- <p><code>#parse_opts</code> is responsable for getting the <code>attr_accessor</code> values prefilled. Since defaults can be specified, it
256
- must negotiate Hashes and use the first key of the hash for the <code>attr_accessor</code>&rsquo;s name.</p>
257
- </td>
258
- <td class=code>
259
- <div class='highlight'><pre> <span class="n">define_method</span> <span class="ss">:parse_opts</span> <span class="k">do</span> <span class="o">|</span><span class="n">opts</span><span class="o">|</span>
260
- <span class="vi">@rep_options</span> <span class="o">=</span> <span class="n">opts</span>
261
- <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">initializiation_args</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">field</span><span class="o">|</span>
262
- <span class="nb">name</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">first</span> <span class="p">:</span> <span class="n">field</span>
263
- <span class="nb">instance_variable_set</span><span class="p">(</span><span class="ss">:&quot;@</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="ss">&quot;</span><span class="p">,</span> <span class="n">opts</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span><span class="p">)</span>
264
- <span class="k">end</span>
265
- <span class="k">end</span>
266
- <span class="k">end</span></pre></div>
267
- </td>
268
- </tr>
269
- <tr id='section-12'>
270
- <td class=docs>
271
- <div class="pilwrap">
272
- <a class="pilcrow" href="#section-12">&#182;</a>
273
- </div>
274
- <p><code>#json_fields</code> setups up some class instance variables to remember sets of top level keys for json structures. Example:</p>
275
-
276
- <pre><code>class A
277
- json_fields [:one, :two, :three] =&gt; :default
278
- end
279
-
280
- A.json_fields(:default) # =&gt; [:one, :two, :three]
281
- </code></pre>
282
-
283
- <p>There is a general assumption that each top level key&rsquo;s value is provided by a method of the same name on an instance
284
- of the class. If this is not true, a Hash syntax can be used to alias to a different method name. Example:</p>
285
-
286
- <pre><code>class A
287
- json_fields [{ :one =&gt; :the_real_one_method }, :two, { :three =&gt; :some_other_three }] =&gt; :default
288
- end
289
- </code></pre>
290
-
291
- <p>Once can also set multiple sets of fields. Example:</p>
292
-
293
- <pre><code>class A
294
- json_fields [:one, :two, :three] =&gt; :default
295
- json_fields [:five, :two, :six] =&gt; :other
296
- end
297
- </code></pre>
298
-
299
- <p>And all fields are returned by calling <code>#json_fields</code> with no args. Example:</p>
300
-
301
- <pre><code>A.json_fields # =&gt; { :default =&gt; [:one, :two, :three], :other =&gt; [:five, :two, :six] }
302
- </code></pre>
303
- </td>
304
- <td class=code>
305
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">json_fields</span><span class="p">(</span><span class="n">arg</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
306
- <span class="k">if</span> <span class="n">arg</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span>
307
- <span class="n">fields</span><span class="p">,</span> <span class="nb">name</span> <span class="o">=</span> <span class="n">arg</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span>
308
- <span class="vi">@json_fields</span> <span class="o">||=</span> <span class="p">{}</span>
309
- <span class="vi">@json_fields</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="o">=</span> <span class="o">[</span><span class="n">fields</span><span class="o">].</span><span class="n">flatten</span>
310
- <span class="k">elsif</span> <span class="n">arg</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Symbol</span><span class="p">)</span>
311
- <span class="vi">@json_fields</span> <span class="o">||=</span> <span class="p">{}</span>
312
- <span class="vi">@json_fields</span><span class="o">[</span><span class="n">arg</span><span class="o">]</span>
313
- <span class="k">elsif</span> <span class="n">arg</span> <span class="o">===</span> <span class="kp">nil</span>
314
- <span class="vi">@json_fields</span> <span class="o">||</span> <span class="p">{}</span>
315
- <span class="k">else</span></pre></div>
316
- </td>
317
- </tr>
318
- <tr id='section-13'>
319
- <td class=docs>
320
- <div class="pilwrap">
321
- <a class="pilcrow" href="#section-13">&#182;</a>
322
- </div>
323
- <p>TODO: make an exception class</p>
324
- </td>
325
- <td class=code>
326
- <div class='highlight'><pre> <span class="k">raise</span> <span class="s2">&quot;You can only use a Hash to set fields, a Symbol to retrieve them, or no argument to retrieve all fields for all names&quot;</span>
327
- <span class="k">end</span>
328
- <span class="k">end</span></pre></div>
329
- </td>
330
- </tr>
331
- <tr id='section-14'>
332
- <td class=docs>
333
- <div class="pilwrap">
334
- <a class="pilcrow" href="#section-14">&#182;</a>
335
- </div>
336
- <p><code>#flat_json_fields</code> is just a utility method to DRY up the next two methods, because their code is almost exactly the same,
337
- it is not intended for use directly and might be confusing.</p>
338
- </td>
339
- <td class=code>
340
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">flat_json_fields</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="ss">:right</span><span class="p">)</span>
341
- <span class="n">side_number</span> <span class="o">=</span> <span class="n">side</span> <span class="o">==</span> <span class="ss">:right</span> <span class="p">?</span> <span class="mi">1</span> <span class="p">:</span> <span class="mi">0</span>
342
-
343
- <span class="n">json_fields</span><span class="o">.</span><span class="n">reduce</span><span class="p">(</span><span class="o">[]</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">memo</span><span class="p">,</span> <span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">fields</span><span class="p">)</span><span class="o">|</span>
344
- <span class="n">memo</span> <span class="o">+</span> <span class="n">fields</span><span class="o">.</span><span class="n">map</span> <span class="k">do</span> <span class="o">|</span><span class="n">field</span><span class="o">|</span>
345
- <span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span>
346
- <span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span><span class="o">[</span><span class="n">side_number</span><span class="o">]</span> <span class="c1"># [name, method_name]</span>
347
- <span class="k">else</span>
348
- <span class="n">field</span>
349
- <span class="k">end</span>
350
- <span class="k">end</span>
351
- <span class="k">end</span><span class="o">.</span><span class="n">uniq</span>
352
- <span class="k">end</span></pre></div>
353
- </td>
354
- </tr>
355
- <tr id='section-15'>
356
- <td class=docs>
357
- <div class="pilwrap">
358
- <a class="pilcrow" href="#section-15">&#182;</a>
359
- </div>
360
- <p>We need a way to get a flat, uniq'ed list of all the fields accross all field sets. This is that.</p>
361
- </td>
362
- <td class=code>
363
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">all_json_fields</span>
364
- <span class="n">flat_json_fields</span><span class="p">(</span><span class="ss">:left</span><span class="p">)</span>
365
- <span class="k">end</span></pre></div>
366
- </td>
367
- </tr>
368
- <tr id='section-16'>
369
- <td class=docs>
370
- <div class="pilwrap">
371
- <a class="pilcrow" href="#section-16">&#182;</a>
372
- </div>
373
- <p>We need a wya to get a flat, uniq'ed list of all the method names accross all field sets. This is that.</p>
374
- </td>
375
- <td class=code>
376
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">all_json_methods</span>
377
- <span class="n">flat_json_fields</span><span class="p">(</span><span class="ss">:right</span><span class="p">)</span>
378
- <span class="k">end</span></pre></div>
379
- </td>
380
- </tr>
381
- <tr id='section-17'>
382
- <td class=docs>
383
- <div class="pilwrap">
384
- <a class="pilcrow" href="#section-17">&#182;</a>
385
- </div>
386
- <p>An easy way to save on GC is to use the same instance to turn an array of objects into hashes instead
387
- of instantiating a new object for every object in the array. Here is an example of it&rsquo;s usage:</p>
388
-
389
- <pre><code>class BookRep
390
- initialize_with :book_model
391
- fields :title =&gt; :default
392
- forward :title =&gt; :book_model
393
- end
394
-
395
- BookRep.shared(:book_model =&gt; Book.first).to_hash # =&gt; { :title =&gt; "Moby Dick" }
396
- BookRep.shared(:book_model =&gt; Book.last).to_hash # =&gt; { :title =&gt; "Lost Horizon" }
397
- </code></pre>
398
-
399
- <p>This should terrify you. If it doesn&rsquo;t, then this example will:</p>
400
-
401
- <pre><code>book1 = BookRep.shared(:book_model =&gt; Book.first)
402
- book2 = BookRep.shared(:book_model =&gt; Book.last)
403
-
404
- boo1.object_id === book2.object_id # =&gt; true
405
- </code></pre>
406
-
407
- <p><strong>It really is a shared object.</strong></p>
408
-
409
- <p>You really shouldn&rsquo;t use this method directly for anything.</p>
410
- </td>
411
- <td class=code>
412
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">shared</span><span class="p">(</span><span class="n">opts</span> <span class="o">=</span> <span class="p">{})</span>
413
- <span class="vi">@pointer</span> <span class="o">=</span> <span class="p">(</span><span class="no">Thread</span><span class="o">.</span><span class="n">current</span><span class="o">[</span><span class="ss">:rep_shared_instances</span><span class="o">]</span> <span class="o">||=</span> <span class="p">{})</span>
414
- <span class="vi">@pointer</span><span class="o">[</span><span class="nb">object_id</span><span class="o">]</span> <span class="o">||=</span> <span class="kp">new</span>
415
- <span class="vi">@pointer</span><span class="o">[</span><span class="nb">object_id</span><span class="o">].</span><span class="n">reset_for_json!</span>
416
- <span class="vi">@pointer</span><span class="o">[</span><span class="nb">object_id</span><span class="o">].</span><span class="n">parse_opts</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
417
- <span class="vi">@pointer</span><span class="o">[</span><span class="nb">object_id</span><span class="o">]</span>
418
- <span class="k">end</span></pre></div>
419
- </td>
420
- </tr>
421
- <tr id='section-18'>
422
- <td class=docs>
423
- <div class="pilwrap">
424
- <a class="pilcrow" href="#section-18">&#182;</a>
425
- </div>
426
- <p>The fanciest thing in this entire library is this <code>#to_proc</code> method. Here is an example of it&rsquo;s usage:</p>
427
-
428
- <pre><code>class BookRep
429
- initialize_with :book_model
430
- fields :title =&gt; :default
431
- forward :title =&gt; :book_model
432
- end
433
-
434
- Book.all.map(&amp;BookRep) # =&gt; [{ :title =&gt; "Moby Dick" }, { :title =&gt; "Lost Horizon " }]
435
- </code></pre>
436
-
437
- <p>And now I will explain how it works. Any object can have a to_proc method and when you call <code>#map</code> on an
438
- array and hand it a proc it will in turn hand each object as an argument to that proc. What I&rsquo;ve decided
439
- to do with this object is use it the options for a shared instance to make a hash.</p>
440
-
441
- <p>Since I know the different initialization argumants from a call to <code>initialize_with</code>, I can infer by order
442
- which object is which option. Then I can create a Hash to give to <code>parse_opts</code> through the <code>shared</code> method.
443
- I hope that makes sense.</p>
444
-
445
- <p>It allows for extremely clean Rails controllers like this:</p>
446
-
447
- <pre><code>class PhotosController &lt; ApplicationController
448
- respond_to :json, :html
449
-
450
- def index
451
- @photos = Photo.paginate(page: params[:page], per_page: 20)
452
- respond_with @photos.map(&amp;PhotoRep)
453
- end
454
-
455
- def show
456
- @photo = Photo.find(params[:id])
457
- respond_with PhotoRep.new(photo: @photo)
458
- end
459
- end
460
- </code></pre>
461
-
462
- </td>
463
- <td class=code>
464
- <div class='highlight'><pre> <span class="k">def</span> <span class="nf">to_proc</span>
465
- <span class="nb">proc</span> <span class="p">{</span> <span class="o">|</span><span class="n">obj</span><span class="o">|</span>
466
- <span class="n">arr</span> <span class="o">=</span> <span class="o">[</span><span class="n">obj</span><span class="o">].</span><span class="n">flatten</span>
467
- <span class="n">init_args</span> <span class="o">=</span> <span class="vi">@initializiation_args</span><span class="o">[</span><span class="mi">0</span><span class="o">.</span><span class="n">.</span><span class="p">(</span><span class="n">arr</span><span class="o">.</span><span class="n">length</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">]</span>
468
- <span class="n">opts</span> <span class="o">=</span> <span class="no">Hash</span><span class="o">[</span><span class="n">init_args</span><span class="o">.</span><span class="n">zip</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="o">]</span>
469
- <span class="n">shared</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span><span class="o">.</span><span class="n">to_hash</span>
470
- <span class="p">}</span>
471
- <span class="k">end</span>
472
- <span class="k">end</span>
473
-
474
- <span class="k">module</span> <span class="nn">MashedSupport</span>
475
- <span class="k">def</span> <span class="nf">to_hash</span><span class="p">(</span><span class="nb">name</span> <span class="o">=</span> <span class="ss">:default</span><span class="p">)</span>
476
- <span class="no">Mashed</span><span class="o">::</span><span class="no">Mash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="k">super</span><span class="p">)</span>
477
- <span class="k">end</span>
478
- <span class="k">end</span>
479
- <span class="k">end</span></pre></div>
480
- </td>
481
- </tr>
482
- </table>
483
- </div>
484
- </body>