coin_rack 0.0.3

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/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rack"
4
+ gem "coin"
5
+ gem "footing", ">=0.1.5"
6
+ gem "rack-abstract-format", :require => "rack/abstract_format"
7
+ gem "rack-accept-media-types", :require => "rack/accept_media_types"
8
+ gem "builder"
9
+ gem "activesupport", :require => "active_support/all"
10
+
11
+ group :development do
12
+ gem "pry"
13
+ gem "pry-stack_explorer"
14
+ gem "micro_test"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,49 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.9)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ binding_of_caller (0.6.8)
8
+ builder (3.1.4)
9
+ coderay (1.0.8)
10
+ coin (0.1.2)
11
+ footing (0.1.5)
12
+ i18n (0.6.1)
13
+ method_source (0.8.1)
14
+ micro_test (0.3.1)
15
+ os
16
+ multi_json (1.4.0)
17
+ os (0.9.6)
18
+ pry (0.9.10)
19
+ coderay (~> 1.0.5)
20
+ method_source (~> 0.8)
21
+ slop (~> 3.3.1)
22
+ pry (0.9.10-java)
23
+ coderay (~> 1.0.5)
24
+ method_source (~> 0.8)
25
+ slop (~> 3.3.1)
26
+ spoon (~> 0.0)
27
+ pry-stack_explorer (0.4.7)
28
+ binding_of_caller (~> 0.6.8)
29
+ rack (1.4.1)
30
+ rack-abstract-format (0.9.9)
31
+ rack-accept-media-types (0.9)
32
+ slop (3.3.3)
33
+ spoon (0.0.1)
34
+
35
+ PLATFORMS
36
+ java
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ activesupport
41
+ builder
42
+ coin
43
+ footing (>= 0.1.5)
44
+ micro_test
45
+ pry
46
+ pry-stack_explorer
47
+ rack
48
+ rack-abstract-format
49
+ rack-accept-media-types
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Nathan Hopkins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # CoinRack
2
+
3
+ A simple [Rack](http://rack.github.com/) application that provides a
4
+ REST interface to [Coin's API](https://github.com/hopsoft/coin).
5
+
6
+ ## Quick Start
7
+
8
+ ### Run the server
9
+
10
+ ```bash
11
+ $ gem install coin_rack
12
+ $ coin_rack --run
13
+ ```
14
+
15
+ ### Make some client requests
16
+
17
+ ```bash
18
+ $ curl --data "value=true" http://localhost:9292/example.json
19
+ # => {"example":true}
20
+
21
+ $ curl http://localhost:9292/example.json
22
+ # => {"example":true}
23
+
24
+ $ curl -X DELETE http://localhost:9292/example.json
25
+ # => {"example":null}
26
+
27
+ $ curl http://localhost:9292/example.json
28
+ # => {"example":null}
29
+ ```
30
+
31
+ #### Prefer XML?
32
+ ```bash
33
+ $ curl --data "value=true" http://localhost:9292/example.xml
34
+ # <?xml version="1.0" encoding="UTF-8"?>
35
+ # <hash>
36
+ # <example type="boolean">true</example>
37
+ # </hash>
38
+
39
+ $ curl http://localhost:9292/example.xml
40
+ # <?xml version="1.0" encoding="UTF-8"?>
41
+ # <hash>
42
+ # <example type="boolean">true</example>
43
+ # </hash>
44
+
45
+ $ curl -X DELETE http://localhost:9292/example.xml
46
+ # <?xml version="1.0" encoding="UTF-8"?>
47
+ # <hash>
48
+ # <example nil="true"/>
49
+ # </hash>
50
+
51
+ $ curl http://localhost:9292/example.xml
52
+ # <?xml version="1.0" encoding="UTF-8"?>
53
+ # <hash>
54
+ # <example nil="true"/>
55
+ # </hash>
56
+ ```
57
+
58
+ ## URL Definition
59
+
60
+ ```
61
+ cache key
62
+ |
63
+ http://localhost:9292/KEY.FORMAT
64
+ |
65
+ response format
66
+ ```
67
+
68
+ *Note: The XML format is also supported but XML examples have been omitted for brevity.*
69
+
70
+ ## POST/PUT
71
+
72
+ Create and/or update the key to a new value.
73
+
74
+ #### Params
75
+
76
+ * **value** - the value to assign
77
+
78
+ #### Request URI
79
+
80
+ ```
81
+ http://localhost:9292/example.json
82
+ ```
83
+
84
+ #### Request Body
85
+
86
+ ```
87
+ value=true
88
+ ```
89
+
90
+ #### Response
91
+
92
+ ```
93
+ "{\"example\":\"true\"}"
94
+ ```
95
+
96
+ ## GET
97
+
98
+ Get the current value for the specified key.
99
+
100
+ #### Request URI
101
+
102
+ ```
103
+ http://localhost:9292/example.json
104
+ ```
105
+
106
+ #### Response
107
+
108
+ ```
109
+ "{\"example\":\"true\"}"
110
+ ```
111
+
112
+ ## DELETE
113
+
114
+ Deletes the key.
115
+
116
+ #### Request URI
117
+
118
+ ```
119
+ http://localhost:9292/example.json
120
+ ```
121
+
122
+ #### Response
123
+
124
+ ```
125
+ "{\"example\":null}"
126
+ ```
data/bin/coin_rack ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby --
2
+ require "optparse"
3
+
4
+ # setup the options -----------------------------------------------------------
5
+ options = {}
6
+ parser = OptionParser.new do |opts|
7
+ opts.banner = "CoinRack Usage: coin_rack [options]"
8
+
9
+ desc = "Prints the location of the rackup file."
10
+ opts.on("-p", "--print", desc) { |value| options[:print] = value }
11
+
12
+ desc = "Starts the Rack server."
13
+ opts.on("-r", "--run", desc) { |value| options[:run] = value }
14
+
15
+ opts.on_tail("-h", "--help", "Show this message.") do
16
+ puts opts
17
+ exit
18
+ end
19
+ end
20
+ parser.parse!
21
+
22
+ if options.values.compact.empty?
23
+ puts parser.banner
24
+ puts parser.summarize
25
+ exit
26
+ end
27
+
28
+ path = File.expand_path(File.join(File.dirname(__FILE__), ".."))
29
+ rackup_file = File.join(path, "config.ru")
30
+
31
+ if options[:print]
32
+ puts rackup_file
33
+ exit
34
+ end
35
+
36
+ if options[:run]
37
+ exec "cd #{path} && rackup"
38
+ exit
39
+ end
data/config.ru ADDED
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), "lib", "coin_rack")
2
+
3
+ use Rack::Static
4
+ use Rack::AbstractFormat
5
+ run CoinRack.new
data/lib/coin_rack.rb ADDED
@@ -0,0 +1,92 @@
1
+ require "bundler"
2
+ Bundler.require
3
+ require File.join(File.dirname(__FILE__), "coin_rack", "version")
4
+
5
+ Footing.patch! String, Footing::String
6
+ Footing.patch! Array, Footing::Array
7
+ Footing.patch! Hash, Footing::Hash
8
+
9
+ class CoinRack
10
+
11
+ def call(env)
12
+ begin
13
+ request = Rack::Request.new(env)
14
+ request.POST.cast_values!
15
+ return favicon if request.path == "/favicon.ico"
16
+ return get(request) if request.get?
17
+ return post(request) if request.post?
18
+ return put(request) if request.put?
19
+ return delete(request) if request.delete?
20
+ rescue Exception => ex
21
+ [500, {"Content-Type" => "text/html"}, ["ERROR: #{ex}"]]
22
+ end
23
+
24
+ [400, {"Content-Type" => "text/html"}, ["BAD REQUEST"]]
25
+ end
26
+
27
+ protected
28
+
29
+ def key(request)
30
+ request.path.gsub(/\A\//, "")
31
+ end
32
+
33
+ def format(request)
34
+ case request.accept_media_types.prefered
35
+ when "application/json" then :json
36
+ when "application/xml" then :xml
37
+ else :unknown
38
+ end
39
+ end
40
+
41
+ # CREATE
42
+ def post(request)
43
+ put(request)
44
+ end
45
+
46
+ # READ
47
+ def get(request)
48
+ k = key(request)
49
+ f = format(request)
50
+ result = {}
51
+ result[k] = Coin.read(k)
52
+ send f, result
53
+ end
54
+
55
+ # UPDATE
56
+ def put(request)
57
+ k = key(request)
58
+ f = format(request)
59
+ value = request.POST["value"]
60
+ Coin.write k, value
61
+ result = {}
62
+ result[k] = value
63
+ send f, result
64
+ end
65
+
66
+ # DELETE
67
+ def delete(request)
68
+ k = key(request)
69
+ f = format(request)
70
+ Coin.delete k
71
+ result = {}
72
+ result[k] = nil
73
+ send f, result
74
+ end
75
+
76
+ def json(result)
77
+ [200, {"Content-Type" => "text/json"}, [result.to_json]]
78
+ end
79
+
80
+ def xml(result)
81
+ [200, {"Content-Type" => "text/xml"}, [result.to_xml]]
82
+ end
83
+
84
+ def unknown
85
+ [400, {"Content-Type" => "text/html"}, ["UNKNOWN FORMAT"]]
86
+ end
87
+
88
+ def favicon
89
+ [200, { "Content-Type" => "test/plain" }, ["about:blank"]]
90
+ end
91
+
92
+ end
@@ -0,0 +1,3 @@
1
+ class CoinRack
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,219 @@
1
+ require "net/http"
2
+ require "net/telnet"
3
+ require "uri"
4
+ require "json"
5
+ require "rexml/document"
6
+ require "bundler"
7
+ Bundler.require :default, :development
8
+
9
+ class CoinRackTest < MicroTest::Test
10
+
11
+ before do
12
+ @path = File.join(File.dirname(__FILE__), "..", "config.ru")
13
+ @pid = spawn({}, "rackup #{@path}")
14
+
15
+ # wait for the server to come up
16
+ sleep 0.1
17
+ t = nil
18
+ begin
19
+ t = Net::Telnet.new "Host" => "localhost", "Port" => 9292
20
+ rescue Exception => ex
21
+ end
22
+ while t.nil?
23
+ begin
24
+ t = Net::Telnet.new "Host" => "localhost", "Port" => 9292
25
+ rescue Exception => ex
26
+ sleep 0.1
27
+ end
28
+ end
29
+
30
+ @uri = URI.parse("http://localhost:9292")
31
+ end
32
+
33
+ after do
34
+ Coin.stop_server
35
+ Process.kill(9, @pid)
36
+ end
37
+
38
+ test "GET JSON data" do
39
+ Coin.write "example", "value"
40
+ http = Net::HTTP.new(@uri.host, @uri.port)
41
+ request = Net::HTTP::Get.new("/example.json")
42
+ response = http.request(request)
43
+ data = JSON.parse(response.body)
44
+ assert response.header["Content-Type"] == "text/json"
45
+ assert response.code == "200"
46
+ assert response.body == "{\"example\":\"value\"}"
47
+ assert data["example"] == "value"
48
+ end
49
+
50
+ test "GET complex JSON data" do
51
+ Coin.write "example", {
52
+ "value1" => true,
53
+ "value2" => [1, 2, 3],
54
+ "nested" => {
55
+ "value1" => false,
56
+ "value2" => [4, 5, 6]
57
+ }
58
+ }
59
+ http = Net::HTTP.new(@uri.host, @uri.port)
60
+ request = Net::HTTP::Get.new("/example.json")
61
+ response = http.request(request)
62
+ assert response.header["Content-Type"] == "text/json"
63
+ assert response.code == "200"
64
+ assert response.body == "{\"example\":{\"value1\":true,\"value2\":[1,2,3],\"nested\":{\"value1\":false,\"value2\":[4,5,6]}}}"
65
+ assert JSON.parse(response.body)
66
+ end
67
+
68
+ test "GET XML data" do
69
+ Coin.write "example", "value"
70
+ http = Net::HTTP.new(@uri.host, @uri.port)
71
+ request = Net::HTTP::Get.new("/example.xml")
72
+ response = http.request(request)
73
+ assert response.header["Content-Type"] == "text/xml"
74
+ assert response.code == "200"
75
+ assert response.body == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <example>value</example>\n</hash>\n"
76
+ assert REXML::Document.new(response.body)
77
+ end
78
+
79
+ test "GET complex XML data" do
80
+ Coin.write "example", {
81
+ "value1" => true,
82
+ "value2" => [1, 2, 3],
83
+ "nested" => {
84
+ "value1" => false,
85
+ "value2" => [4, 5, 6]
86
+ }
87
+ }
88
+ http = Net::HTTP.new(@uri.host, @uri.port)
89
+ request = Net::HTTP::Get.new("/example.xml")
90
+ response = http.request(request)
91
+ assert response.header["Content-Type"] == "text/xml"
92
+ assert response.code == "200"
93
+ assert response.body == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <example>\n <value1 type=\"boolean\">true</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">1</value2>\n <value2 type=\"integer\">2</value2>\n <value2 type=\"integer\">3</value2>\n </value2>\n <nested>\n <value1 type=\"boolean\">false</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">4</value2>\n <value2 type=\"integer\">5</value2>\n <value2 type=\"integer\">6</value2>\n </value2>\n </nested>\n </example>\n</hash>\n"
94
+ assert REXML::Document.new(response.body)
95
+ end
96
+
97
+ test "POST returning JSON" do
98
+ example = {
99
+ "value" => {
100
+ "value1" => true,
101
+ "value2" => [1, 2, 3],
102
+ "nested" => {
103
+ "value1" => false,
104
+ "value2" => [4, 5, 6]
105
+ }
106
+ }
107
+ }
108
+ http = Net::HTTP.new(@uri.host, @uri.port)
109
+ request = Net::HTTP::Post.new("/example.json")
110
+ request.body = example.to_param
111
+ response = http.request(request)
112
+ assert response.header["Content-Type"] == "text/json"
113
+ assert response.code == "200"
114
+ assert response.body == "{\"example\":{\"nested\":{\"value1\":false,\"value2\":[4,5,6]},\"value1\":true,\"value2\":[1,2,3]}}"
115
+ assert JSON.parse(response.body)
116
+ cached = Coin.read("example")
117
+ assert (cached.keys - example["value"].keys).empty?
118
+ assert (cached.values - example["value"].values).empty?
119
+ end
120
+
121
+ test "POST returning XML" do
122
+ example = {
123
+ "value" => {
124
+ "value1" => true,
125
+ "value2" => [1, 2, 3],
126
+ "nested" => {
127
+ "value1" => false,
128
+ "value2" => [4, 5, 6]
129
+ }
130
+ }
131
+ }
132
+ http = Net::HTTP.new(@uri.host, @uri.port)
133
+ request = Net::HTTP::Post.new("/example.xml")
134
+ request.body = example.to_param
135
+ response = http.request(request)
136
+ assert response.header["Content-Type"] == "text/xml"
137
+ assert response.code == "200"
138
+ assert response.body == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <example>\n <nested>\n <value1 type=\"boolean\">false</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">4</value2>\n <value2 type=\"integer\">5</value2>\n <value2 type=\"integer\">6</value2>\n </value2>\n </nested>\n <value1 type=\"boolean\">true</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">1</value2>\n <value2 type=\"integer\">2</value2>\n <value2 type=\"integer\">3</value2>\n </value2>\n </example>\n</hash>\n"
139
+ assert REXML::Document.new(response.body)
140
+ cached = Coin.read("example")
141
+ assert (cached.keys - example["value"].keys).empty?
142
+ assert (cached.values - example["value"].values).empty?
143
+ end
144
+
145
+ test "PUT returning JSON" do
146
+ example = {
147
+ "value" => {
148
+ "value1" => true,
149
+ "value2" => [1, 2, 3],
150
+ "nested" => {
151
+ "value1" => false,
152
+ "value2" => [4, 5, 6]
153
+ }
154
+ }
155
+ }
156
+ http = Net::HTTP.new(@uri.host, @uri.port)
157
+ request = Net::HTTP::Put.new("/example.json")
158
+ request.body = example.to_param
159
+ response = http.request(request)
160
+ assert response.header["Content-Type"] == "text/json"
161
+ assert response.code == "200"
162
+ assert response.body == "{\"example\":{\"nested\":{\"value1\":false,\"value2\":[4,5,6]},\"value1\":true,\"value2\":[1,2,3]}}"
163
+ assert JSON.parse(response.body)
164
+ cached = Coin.read("example")
165
+ assert (cached.keys - example["value"].keys).empty?
166
+ assert (cached.values - example["value"].values).empty?
167
+ end
168
+
169
+ test "PUT returning XML" do
170
+ example = {
171
+ "value" => {
172
+ "value1" => true,
173
+ "value2" => [1, 2, 3],
174
+ "nested" => {
175
+ "value1" => false,
176
+ "value2" => [4, 5, 6]
177
+ }
178
+ }
179
+ }
180
+ http = Net::HTTP.new(@uri.host, @uri.port)
181
+ request = Net::HTTP::Put.new("/example.xml")
182
+ request.body = example.to_param
183
+ response = http.request(request)
184
+ assert response.header["Content-Type"] == "text/xml"
185
+ assert response.code == "200"
186
+ assert response.body == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <example>\n <nested>\n <value1 type=\"boolean\">false</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">4</value2>\n <value2 type=\"integer\">5</value2>\n <value2 type=\"integer\">6</value2>\n </value2>\n </nested>\n <value1 type=\"boolean\">true</value1>\n <value2 type=\"array\">\n <value2 type=\"integer\">1</value2>\n <value2 type=\"integer\">2</value2>\n <value2 type=\"integer\">3</value2>\n </value2>\n </example>\n</hash>\n"
187
+ assert REXML::Document.new(response.body)
188
+ cached = Coin.read("example")
189
+ assert (cached.keys - example["value"].keys).empty?
190
+ assert (cached.values - example["value"].values).empty?
191
+ end
192
+
193
+ test "DELETE returning JSON" do
194
+ Coin.write "example", "value"
195
+ assert Coin.read("example") == "value"
196
+ http = Net::HTTP.new(@uri.host, @uri.port)
197
+ request = Net::HTTP::Delete.new("/example.json")
198
+ response = http.request(request)
199
+ data = JSON.parse(response.body)
200
+ assert response.header["Content-Type"] == "text/json"
201
+ assert response.code == "200"
202
+ assert response.body == "{\"example\":null}"
203
+ assert Coin.read("example").nil?
204
+ end
205
+
206
+ test "DELETE returning XML" do
207
+ Coin.write "example", "value"
208
+ assert Coin.read("example") == "value"
209
+ http = Net::HTTP.new(@uri.host, @uri.port)
210
+ request = Net::HTTP::Delete.new("/example.xml")
211
+ response = http.request(request)
212
+ assert response.header["Content-Type"] == "text/xml"
213
+ assert response.code == "200"
214
+ assert response.body == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <example nil=\"true\"/>\n</hash>\n"
215
+ assert REXML::Document.new(response.body)
216
+ assert Coin.read("example").nil?
217
+ end
218
+
219
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coin_rack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Hopkins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: coin
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
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: footing
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
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: rack-abstract-format
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
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: rack-accept-media-types
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: builder
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: activesupport
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description:
127
+ email:
128
+ - natehop@gmail.com
129
+ executables:
130
+ - coin_rack
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - lib/coin_rack/version.rb
135
+ - lib/coin_rack.rb
136
+ - bin/coin_rack
137
+ - test/coin_rack_test.rb
138
+ - config.ru
139
+ - Gemfile
140
+ - Gemfile.lock
141
+ - LICENSE.txt
142
+ - README.md
143
+ homepage: https://github.com/hopsoft/coin_rack
144
+ licenses: []
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 1.8.23
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: A Simple Rack application that provides a REST interface for Coin.
167
+ test_files: []
168
+ has_rdoc: