rep 0.0.1 → 0.0.2
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/.travis.yml +11 -0
- data/README.md +8 -14
- data/Rakefile +18 -1
- data/docs/index.html +478 -0
- data/docs/lib/rep.html +478 -0
- data/docs/lib/rep/version.html +44 -0
- data/docs/rep.html +478 -0
- data/docs/rep/version.html +44 -0
- data/lib/rep.rb +180 -16
- data/lib/rep/version.rb +1 -1
- data/rep.gemspec +4 -0
- data/test/lib/rep_test.rb +47 -13
- data/test/test_helper.rb +0 -6
- metadata +72 -2
@@ -0,0 +1,44 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
+
<title>version.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 …
|
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="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>version.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">¶</a>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
|
35
|
+
</td>
|
36
|
+
<td class=code>
|
37
|
+
<div class='highlight'><pre><span class="k">module</span> <span class="nn">Rep</span>
|
38
|
+
<span class="no">VERSION</span> <span class="o">=</span> <span class="s2">"0.0.1"</span>
|
39
|
+
<span class="k">end</span></pre></div>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
</table>
|
43
|
+
</div>
|
44
|
+
</body>
|
data/lib/rep.rb
CHANGED
@@ -1,13 +1,51 @@
|
|
1
|
-
|
1
|
+
# **Rep** is a small module to endow any class to make json quickly. It solves four problems:
|
2
|
+
#
|
3
|
+
# 1. Enumerating top level keys for a json structure
|
4
|
+
# 2. Providing a convention for the value of those keys
|
5
|
+
# 3. Defining `attr_accessor`'s that are prefilled from an options hash given to `#initialize`
|
6
|
+
# 4. Sharing instances to help GC
|
7
|
+
#
|
8
|
+
# The code is available on [github](http://github.com/myobie/rep).
|
9
|
+
|
10
|
+
# `Forwardable` is in the stdlib and allows ruby objects to delegate methods off to other objects. An example:
|
11
|
+
#
|
12
|
+
# class A
|
13
|
+
# extend Forwardable
|
14
|
+
# delegate [:length, :first] => :@array
|
15
|
+
# def initialize(array = [])
|
16
|
+
# @array = array
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# A.new([1,2,3]).length # => 3
|
21
|
+
# A.new([1,2,3]).first # => 1
|
22
|
+
|
2
23
|
require 'forwardable'
|
24
|
+
|
25
|
+
# `JSON::generate` and `JSON::decode` are much safer to use than `Object#to_json`.
|
26
|
+
|
3
27
|
require 'json'
|
4
28
|
|
29
|
+
require 'rep/version'
|
5
30
|
module Rep
|
31
|
+
|
32
|
+
# All classes that `include Rep` are extended with `Forwardable`,
|
33
|
+
# given some aliases, endowned with `HashieSupport` if Hashie is loaded,
|
34
|
+
# and given a delegate method if it doesn't already have one.
|
35
|
+
|
6
36
|
def self.included(klass)
|
7
37
|
klass.extend Forwardable
|
8
38
|
klass.extend ClassMethods
|
9
39
|
klass.instance_eval {
|
10
40
|
class << self
|
41
|
+
unless defined?(delegate)
|
42
|
+
def delegate(opts = {})
|
43
|
+
methods, object_name = opts.to_a.first
|
44
|
+
args = [object_name, methods].flatten
|
45
|
+
def_delegators *args
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
11
49
|
alias forward delegate
|
12
50
|
|
13
51
|
unless defined?(fields)
|
@@ -18,21 +56,29 @@ module Rep
|
|
18
56
|
include HashieSupport
|
19
57
|
end
|
20
58
|
end
|
21
|
-
|
22
|
-
unless defined?(parse_opts)
|
23
|
-
def parse_opts(opts = {})
|
24
|
-
# NOOP
|
25
|
-
end
|
26
|
-
end
|
27
59
|
}
|
28
60
|
end
|
29
61
|
|
62
|
+
# Since a goal is to be able to share instances, we need an easy way to reset a
|
63
|
+
# shared instance back to factory defaults. If you memoize any methods that are
|
64
|
+
# not declared as json fields, then overried this method and set any memoized
|
65
|
+
# variables to nil, then super.
|
66
|
+
|
30
67
|
def reset_for_json!
|
31
68
|
self.class.all_json_methods.each do |method_name|
|
32
69
|
instance_variable_set(:"@#{method_name}", nil)
|
33
70
|
end
|
34
71
|
end
|
35
72
|
|
73
|
+
# All the work of generating a hash from an instance is packaged up in one method. Since
|
74
|
+
# fields can be aliases in the format `{ :json_key_name => :method_name }`, there
|
75
|
+
# is some fancy logic to determine the `field_name` and `method_name` variables.
|
76
|
+
#
|
77
|
+
# { :one => :foo }.to_a # => [[:one, :foo]]
|
78
|
+
#
|
79
|
+
# Right now it will raise if either a field doesn't have a method to provide it's value or
|
80
|
+
# if there are no json fields setup for the particular set (which defaults to `:default`).
|
81
|
+
|
36
82
|
def to_hash(name = :default)
|
37
83
|
if fields = self.class.json_fields(name)
|
38
84
|
fields.reduce({}) do |memo, field|
|
@@ -55,6 +101,15 @@ module Rep
|
|
55
101
|
end
|
56
102
|
|
57
103
|
module ClassMethods
|
104
|
+
|
105
|
+
# Defines an attr_accessor with a default value. The default for default is nil. Example:
|
106
|
+
#
|
107
|
+
# class A
|
108
|
+
# register_accessor :name => "No Name"
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# A.new.name # => "No Name"
|
112
|
+
|
58
113
|
def register_accessor(acc)
|
59
114
|
name, default = acc.is_a?(Hash) ? acc.to_a.first : [acc, nil]
|
60
115
|
attr_accessor name
|
@@ -66,19 +121,38 @@ module Rep
|
|
66
121
|
end
|
67
122
|
end
|
68
123
|
|
124
|
+
# Defines an `#initialize` method that accepts a Hash argument and copies some keys out into `attr_accessors`.
|
125
|
+
# If your class already has an `#iniatialize` method then this will overwrite it (so don't use it). `#initialize_with`
|
126
|
+
# does not have to be used to use any other parts of Rep.
|
127
|
+
|
69
128
|
def initialize_with(*args)
|
70
129
|
@initializiation_args = args
|
71
130
|
|
72
|
-
|
73
|
-
|
131
|
+
# Remember what args we normally initialize with so we can refer to them when building shared instances.
|
132
|
+
|
133
|
+
if defined?(define_singleton_method)
|
134
|
+
define_singleton_method :initializiation_args do
|
135
|
+
@initializiation_args
|
136
|
+
end
|
137
|
+
else
|
138
|
+
singleton = class << self; self end
|
139
|
+
singleton.send :define_method, :initializiation_args, lambda { @initializiation_args }
|
74
140
|
end
|
75
141
|
|
142
|
+
# Create an `attr_accessor` for each one. Defaults can be provided using the Hash version { :arg => :default_value }
|
143
|
+
|
76
144
|
args.each { |a| register_accessor(a) }
|
77
145
|
|
78
|
-
define_method(:initialize) { |
|
146
|
+
define_method(:initialize) { |*args|
|
147
|
+
opts = args.first || {}
|
148
|
+
parse_opts(opts)
|
149
|
+
}
|
150
|
+
|
151
|
+
# `#parse_opts` is responsable for getting the `attr_accessor` values prefilled. Since defaults can be specified, it
|
152
|
+
# must negotiate Hashes and use the first key of the hash for the `attr_accessor`'s name.
|
79
153
|
|
80
154
|
define_method :parse_opts do |opts|
|
81
|
-
@
|
155
|
+
@rep_options = opts
|
82
156
|
self.class.initializiation_args.each do |field|
|
83
157
|
name = field.is_a?(Hash) ? field.to_a.first.first : field
|
84
158
|
instance_variable_set(:"@#{name}", opts[name])
|
@@ -86,6 +160,32 @@ module Rep
|
|
86
160
|
end
|
87
161
|
end
|
88
162
|
|
163
|
+
# `#json_fields` setups up some class instance variables to remember sets of top level keys for json structures. Example:
|
164
|
+
#
|
165
|
+
# class A
|
166
|
+
# json_fields [:one, :two, :three] => :default
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# A.json_fields(:default) # => [:one, :two, :three]
|
170
|
+
#
|
171
|
+
# There is a general assumption that each top level key's value is provided by a method of the same name on an instance
|
172
|
+
# of the class. If this is not true, a Hash syntax can be used to alias to a different method name. Example:
|
173
|
+
#
|
174
|
+
# class A
|
175
|
+
# json_fields [{ :one => :the_real_one_method }, :two, { :three => :some_other_three }] => :default
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# Once can also set multiple sets of fields. Example:
|
179
|
+
#
|
180
|
+
# class A
|
181
|
+
# json_fields [:one, :two, :three] => :default
|
182
|
+
# json_fields [:five, :two, :six] => :other
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# And all fields are returned by calling `#json_fields` with no args. Example:
|
186
|
+
#
|
187
|
+
# A.json_fields # => { :default => [:one, :two, :three], :other => [:five, :two, :six] }
|
188
|
+
|
89
189
|
def json_fields(arg = nil)
|
90
190
|
if arg.is_a?(Hash)
|
91
191
|
fields, name = arg.to_a.first
|
@@ -102,6 +202,9 @@ module Rep
|
|
102
202
|
end
|
103
203
|
end
|
104
204
|
|
205
|
+
# `#flat_json_fields` is just a utility method to DRY up the next two methods, because their code is almost exactly the same,
|
206
|
+
# it is not intended for use directly and might be confusing.
|
207
|
+
|
105
208
|
def flat_json_fields(side = :right)
|
106
209
|
side_number = side == :right ? 1 : 0
|
107
210
|
|
@@ -116,22 +219,83 @@ module Rep
|
|
116
219
|
end.uniq
|
117
220
|
end
|
118
221
|
|
222
|
+
# We need a way to get a flat, uniq'ed list of all the fields accross all field sets. This is that.
|
223
|
+
|
119
224
|
def all_json_fields
|
120
225
|
flat_json_fields(:left)
|
121
226
|
end
|
122
227
|
|
228
|
+
# We need a wya to get a flat, uniq'ed list of all the method names accross all field sets. This is that.
|
229
|
+
|
123
230
|
def all_json_methods
|
124
231
|
flat_json_fields(:right)
|
125
232
|
end
|
126
233
|
|
127
|
-
#
|
234
|
+
# An easy way to save on GC is to use the same instance to turn an array of objects into hashes instead
|
235
|
+
# of instantiating a new object for every object in the array. Here is an example of it's usage:
|
236
|
+
#
|
237
|
+
# class BookRep
|
238
|
+
# initialize_with :book_model
|
239
|
+
# fields :title => :default
|
240
|
+
# forward :title => :book_model
|
241
|
+
# end
|
242
|
+
#
|
243
|
+
# BookRep.shared(:book_model => Book.first).to_hash # => { :title => "Moby Dick" }
|
244
|
+
# BookRep.shared(:book_model => Book.last).to_hash # => { :title => "Lost Horizon" }
|
245
|
+
#
|
246
|
+
# This should terrify you. If it doesn't, then this example will:
|
247
|
+
#
|
248
|
+
# book1 = BookRep.shared(:book_model => Book.first)
|
249
|
+
# book2 = BookRep.shared(:book_model => Book.last)
|
250
|
+
#
|
251
|
+
# boo1.object_id === book2.object_id # => true
|
252
|
+
#
|
253
|
+
# **It really is a shared object.**
|
254
|
+
#
|
255
|
+
# You really shouldn't use this method directly for anything.
|
256
|
+
|
128
257
|
def shared(opts = {})
|
129
|
-
@
|
130
|
-
@
|
131
|
-
@
|
132
|
-
@
|
258
|
+
@pointer = (Thread.current[:rep_shared_instances] ||= {})
|
259
|
+
@pointer[object_id] ||= new
|
260
|
+
@pointer[object_id].reset_for_json!
|
261
|
+
@pointer[object_id].parse_opts(opts)
|
262
|
+
@pointer[object_id]
|
133
263
|
end
|
134
264
|
|
265
|
+
# The fanciest thing in this entire library is this `#to_proc` method. Here is an example of it's usage:
|
266
|
+
#
|
267
|
+
# class BookRep
|
268
|
+
# initialize_with :book_model
|
269
|
+
# fields :title => :default
|
270
|
+
# forward :title => :book_model
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
# Book.all.map(&BookRep) # => [{ :title => "Moby Dick" }, { :title => "Lost Horizon " }]
|
274
|
+
#
|
275
|
+
# And now I will explain how it works. Any object can have a to_proc method and when you call `#map` on an
|
276
|
+
# array and hand it a proc it will in turn hand each object as an argument to that proc. What I've decided
|
277
|
+
# to do with this object is use it the options for a shared instance to make a hash.
|
278
|
+
#
|
279
|
+
# Since I know the different initialization argumants from a call to `initialize_with`, I can infer by order
|
280
|
+
# which object is which option. Then I can create a Hash to give to `parse_opts` through the `shared` method.
|
281
|
+
# I hope that makes sense.
|
282
|
+
#
|
283
|
+
# It allows for extremely clean Rails controllers like this:
|
284
|
+
#
|
285
|
+
# class PhotosController < ApplicationController
|
286
|
+
# respond_to :json, :html
|
287
|
+
#
|
288
|
+
# def index
|
289
|
+
# @photos = Photo.paginate(page: params[:page], per_page: 20)
|
290
|
+
# respond_with @photos.map(&PhotoRep)
|
291
|
+
# end
|
292
|
+
#
|
293
|
+
# def show
|
294
|
+
# @photo = Photo.find(params[:id])
|
295
|
+
# respond_with PhotoRep.new(photo: @photo)
|
296
|
+
# end
|
297
|
+
# end
|
298
|
+
|
135
299
|
def to_proc
|
136
300
|
proc { |obj|
|
137
301
|
arr = [obj].flatten
|
data/lib/rep/version.rb
CHANGED
data/rep.gemspec
CHANGED
@@ -17,4 +17,8 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.add_dependency 'json'
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'minitest'
|
22
|
+
gem.add_development_dependency 'rocco'
|
23
|
+
gem.add_development_dependency 'rdiscount'
|
20
24
|
end
|
data/test/lib/rep_test.rb
CHANGED
@@ -23,10 +23,6 @@ describe Rep do
|
|
23
23
|
new_rep_class.must_respond_to :fields
|
24
24
|
end
|
25
25
|
|
26
|
-
it "has a parse_opts method" do
|
27
|
-
new_rep_class.must_respond_to :parse_opts
|
28
|
-
end
|
29
|
-
|
30
26
|
it "can have fields" do
|
31
27
|
klass = new_rep_class do
|
32
28
|
fields [:foo, :bar] => :default
|
@@ -38,24 +34,24 @@ describe Rep do
|
|
38
34
|
klass = new_rep_class do
|
39
35
|
initialize_with :foo, :bar
|
40
36
|
end
|
41
|
-
inst = klass.new(foo
|
37
|
+
inst = klass.new(:foo => 'foo123')
|
42
38
|
inst.foo.must_equal 'foo123'
|
43
39
|
inst.bar.must_be_nil
|
44
40
|
end
|
45
41
|
|
46
42
|
it "can have default initialization options" do
|
47
43
|
klass = new_rep_class do
|
48
|
-
initialize_with :foo, { bar
|
44
|
+
initialize_with :foo, { :bar => "barbar" }
|
49
45
|
end
|
50
|
-
inst = klass.new(foo
|
46
|
+
inst = klass.new(:foo => 'foofoo')
|
51
47
|
inst.bar.must_equal 'barbar'
|
52
48
|
end
|
53
49
|
|
54
50
|
it "can overried default initialization options" do
|
55
51
|
klass = new_rep_class do
|
56
|
-
initialize_with :foo, { bar
|
52
|
+
initialize_with :foo, { :bar => "barbar" }
|
57
53
|
end
|
58
|
-
inst = klass.new(bar
|
54
|
+
inst = klass.new(:bar => 'notbar')
|
59
55
|
inst.bar.must_equal 'notbar'
|
60
56
|
inst.foo.must_be_nil
|
61
57
|
end
|
@@ -84,7 +80,7 @@ describe Rep do
|
|
84
80
|
def two; 2; end
|
85
81
|
def three; 3; end
|
86
82
|
end
|
87
|
-
klass.new.to_hash.must_equal one
|
83
|
+
klass.new.to_hash.must_equal :one => 1, :two => 2, :three => 3
|
88
84
|
end
|
89
85
|
|
90
86
|
it "should send fields to instance to make json" do
|
@@ -133,10 +129,48 @@ describe Rep do
|
|
133
129
|
fields :keys => :default
|
134
130
|
forward :keys => :hash
|
135
131
|
end
|
136
|
-
hashes = [{ one
|
137
|
-
{ three
|
138
|
-
{ one
|
132
|
+
hashes = [{ :one => 1, :two => 2 },
|
133
|
+
{ :three => 3, :four => 4 },
|
134
|
+
{ :one => 1, :five => 5 }]
|
139
135
|
hashes.map(&klass).to_json.must_equal '[{"keys":["one","two"]},{"keys":["three","four"]},{"keys":["one","five"]}]'
|
140
136
|
end
|
141
137
|
|
138
|
+
describe "shared" do
|
139
|
+
|
140
|
+
User = Struct.new(:name, :age)
|
141
|
+
def users
|
142
|
+
@users ||= %w(Nathan 28 Jason 31 Justin 23).each_slice(2).
|
143
|
+
map { |name, age| User.new(name, age.to_i) }
|
144
|
+
end
|
145
|
+
class UserRep
|
146
|
+
include Rep
|
147
|
+
initialize_with :user
|
148
|
+
fields [:name, :age, :random_number] => :default
|
149
|
+
forward fields(:default) => :user
|
150
|
+
|
151
|
+
def random_number
|
152
|
+
@random_number ||= rand(100)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should memoize random_number" do
|
157
|
+
rep = UserRep.new(:user => users.first)
|
158
|
+
rep.random_number.must_equal rep.random_number
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should get a clean instance each time" do
|
162
|
+
num1 = UserRep.shared(:user => users.first).random_number
|
163
|
+
num2 = UserRep.shared(:user => users.first).random_number
|
164
|
+
num1.wont_equal num2
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should be really really shared" do
|
168
|
+
rep1 = UserRep.shared(:user => users.first)
|
169
|
+
rep2 = UserRep.shared(:user => users.last)
|
170
|
+
rep1.must_equal rep2
|
171
|
+
rep1.name.must_equal rep2.name
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
142
176
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -27,6 +27,70 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: minitest
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rocco
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rdiscount
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
30
94
|
description: A library for writing authoritative representations of objects for pages
|
31
95
|
and apis.
|
32
96
|
email:
|
@@ -36,10 +100,16 @@ extensions: []
|
|
36
100
|
extra_rdoc_files: []
|
37
101
|
files:
|
38
102
|
- .gitignore
|
103
|
+
- .travis.yml
|
39
104
|
- Gemfile
|
40
105
|
- LICENSE.txt
|
41
106
|
- README.md
|
42
107
|
- Rakefile
|
108
|
+
- docs/index.html
|
109
|
+
- docs/lib/rep.html
|
110
|
+
- docs/lib/rep/version.html
|
111
|
+
- docs/rep.html
|
112
|
+
- docs/rep/version.html
|
43
113
|
- lib/rep.rb
|
44
114
|
- lib/rep/version.rb
|
45
115
|
- rep.gemspec
|