rep 0.1.1 → 0.9.1

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.
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>