redsquare 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/README.md +189 -2
- data/bin/redsquare +7 -3
- data/lib/redsquare/{application/app.rb → app.rb} +18 -6
- data/lib/redsquare/config.rb +18 -0
- data/lib/redsquare/version.rb +1 -1
- data/lib/redsquare.rb +10 -1
- data/redsquare.gemspec +6 -3
- data/spec/app_spec.rb +197 -0
- data/spec/spec_helper.rb +11 -0
- metadata +40 -8
- data/lib/redsquare/application/commands/keys.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbc88f827c0b6a085537558c2a5ad96084fe1999
|
4
|
+
data.tar.gz: 92409c95a47bd14731bbf08aaaf5f7de4c70289c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03465cef0c7afead904f05e843824e1f412905ef3e3f8667a3743506e86b3b041c01b8eed37232833929f7b0182f5687df035c85e81661dcb8f7b832ea8bf870
|
7
|
+
data.tar.gz: 792e2aca3fcb850ddb611dab6eca700a07eb9077c4189d6d19b09a23bb4cde4ce7c1f55868c402e9ba3a2253b7747e6b95731754df67810678038025be161d79
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Redsquare
|
2
2
|
|
3
|
-
|
3
|
+
Redsquare provides an HTTP interface for Redis that can be launched as a
|
4
|
+
standalone Sinatra app or mounted within a Rails application.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -16,9 +17,195 @@ Or install it yourself as:
|
|
16
17
|
|
17
18
|
$ gem install redsquare
|
18
19
|
|
20
|
+
## Setup
|
21
|
+
|
22
|
+
### Configuration
|
23
|
+
|
24
|
+
Redsquare config begins and ends with setting a connection to the Redis
|
25
|
+
instance you want to use. If you specify none, then you'll get a
|
26
|
+
connection to localhost on the default Redis port. If you want to
|
27
|
+
specify a connection, use the following:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
Redsquare.configure do |config|
|
31
|
+
|
32
|
+
# set it to an existing connection
|
33
|
+
config.redis = Redis.current
|
34
|
+
|
35
|
+
# pass a config hash that will be passed to Redis.new
|
36
|
+
config.redis = { :host => 'localhost', :port => 6379 }
|
37
|
+
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
### Standalone Server
|
42
|
+
|
43
|
+
Simply run Redsquare from the command line.
|
44
|
+
|
45
|
+
```
|
46
|
+
redsquare
|
47
|
+
|
48
|
+
redsquare ~/some/path/to/redsquare_config.rb
|
49
|
+
```
|
50
|
+
|
51
|
+
### Mounting Within a Rails App
|
52
|
+
|
53
|
+
In your `routes.rb` file simplye mount the `Redsquare::App` module.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
YourApp::Application.routes.draw do
|
57
|
+
mount Redsquare::App => "/redis"
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
19
61
|
## Usage
|
20
62
|
|
21
|
-
|
63
|
+
Using Redsquare is very simple. Commands are divided into two
|
64
|
+
categories, those you issue with an HTTP POST call and those you issue
|
65
|
+
with an HTTP GET call. The examples below will be in JavaScript but you
|
66
|
+
can easily call Redsquare endpoints form anywhere.
|
67
|
+
|
68
|
+
### GET Commands
|
69
|
+
|
70
|
+
The following are the Redis commands which Redsquare knows about that
|
71
|
+
can be called with a GET request:
|
72
|
+
|
73
|
+
```
|
74
|
+
dbsize
|
75
|
+
exists
|
76
|
+
get
|
77
|
+
getbit
|
78
|
+
getrange
|
79
|
+
hexists
|
80
|
+
hget
|
81
|
+
hgetall
|
82
|
+
hkeys
|
83
|
+
hlen
|
84
|
+
hmget
|
85
|
+
hvals
|
86
|
+
keys
|
87
|
+
lindex
|
88
|
+
llen
|
89
|
+
lrange
|
90
|
+
mget
|
91
|
+
pttl
|
92
|
+
randomkey
|
93
|
+
scard
|
94
|
+
sdiff
|
95
|
+
sinter
|
96
|
+
sismember
|
97
|
+
smembers
|
98
|
+
srandmember
|
99
|
+
sunion
|
100
|
+
```
|
101
|
+
|
102
|
+
The URL format for GET commands is straightforward:
|
103
|
+
|
104
|
+
```
|
105
|
+
GET /<command>/<arg1>/<arg2>/<arg...>
|
106
|
+
```
|
107
|
+
|
108
|
+
Some examples:
|
109
|
+
|
110
|
+
```
|
111
|
+
GET /get/somekey
|
112
|
+
GET /keys
|
113
|
+
GET /hget/somekey/somefield
|
114
|
+
```
|
115
|
+
|
116
|
+
The return value is a simple JSON object:
|
117
|
+
|
118
|
+
```javascript
|
119
|
+
// GET /get/somekey
|
120
|
+
{ result: "foo" }
|
121
|
+
|
122
|
+
// GET /keys
|
123
|
+
{ result: ["somekey", "someotherkey"]
|
124
|
+
|
125
|
+
// GET /hget/somekey/somefield
|
126
|
+
{ result: "baz" }
|
127
|
+
```
|
128
|
+
|
129
|
+
### POST Commands
|
130
|
+
|
131
|
+
The following are the Redis commands which Redsquare knows about that
|
132
|
+
can be called with a POST request:
|
133
|
+
|
134
|
+
```
|
135
|
+
sunionstore
|
136
|
+
srem
|
137
|
+
spop
|
138
|
+
smove
|
139
|
+
setrange
|
140
|
+
setnx
|
141
|
+
setbit
|
142
|
+
set
|
143
|
+
sdiffstore
|
144
|
+
sadd
|
145
|
+
rpush
|
146
|
+
rpoplpush
|
147
|
+
rpop
|
148
|
+
renamex
|
149
|
+
rename
|
150
|
+
psetex
|
151
|
+
pexpireat
|
152
|
+
pexpire
|
153
|
+
persist
|
154
|
+
msetnx
|
155
|
+
mset
|
156
|
+
ltrim
|
157
|
+
lset
|
158
|
+
lrem
|
159
|
+
lpushx
|
160
|
+
lpush
|
161
|
+
lpop
|
162
|
+
linsert
|
163
|
+
incrbyfloat
|
164
|
+
incrby
|
165
|
+
incr
|
166
|
+
hsetnx
|
167
|
+
hset
|
168
|
+
hmset
|
169
|
+
hincrbyfloat
|
170
|
+
hincrby
|
171
|
+
hdel
|
172
|
+
getset
|
173
|
+
expireat
|
174
|
+
expire
|
175
|
+
del
|
176
|
+
decrby
|
177
|
+
decr
|
178
|
+
append
|
179
|
+
```
|
180
|
+
|
181
|
+
Because these are POST commands and the arguments may be more complex
|
182
|
+
types than simple strings the semantics of the request are slightly
|
183
|
+
different. Each URL follows the same format:
|
184
|
+
|
185
|
+
```
|
186
|
+
POST /<command>
|
187
|
+
```
|
188
|
+
|
189
|
+
Arguments are supplied via the POST parameter `args` which is an array
|
190
|
+
of arguments in the order that they would be passed to the underlying
|
191
|
+
Redis method. For example:
|
192
|
+
|
193
|
+
```javascript
|
194
|
+
// Sets the 'somefield' field of the hash at key 'somekey' to 42
|
195
|
+
$.post("/hset", { args: ["somekey", "somefield", 42] });
|
196
|
+
|
197
|
+
// Increments the key at 'somekey' by 12
|
198
|
+
$.post("/incrby", { args: ["somekey", 12] });
|
199
|
+
```
|
200
|
+
|
201
|
+
The return value for POST commands is the same for GET commands, a
|
202
|
+
simple JSON hash with a `results` key containing the serialized return
|
203
|
+
value of the Redis call.
|
204
|
+
|
205
|
+
## TODO:
|
206
|
+
|
207
|
+
* Not all of the Redis commands are currently supported.
|
208
|
+
* Add support for Redis pub/sub.
|
22
209
|
|
23
210
|
## Contributing
|
24
211
|
|
data/bin/redsquare
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
def run
|
4
4
|
require "redsquare"
|
5
|
+
require File.expand_path(ARGV[0]) if ARGV[0]
|
5
6
|
Redsquare::App.run!
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
run
|
6
11
|
rescue LoadError => e
|
7
12
|
require "rubygems"
|
8
13
|
path = File.expand_path "../../lib", __FILE__
|
9
14
|
$:.unshift(path) if File.directory?(path) && !$:.include?(path)
|
10
|
-
|
11
|
-
Redsquare::App.run!
|
15
|
+
run
|
12
16
|
end
|
@@ -2,6 +2,10 @@ module Redsquare
|
|
2
2
|
class App < Sinatra::Base
|
3
3
|
|
4
4
|
POST_COMMANDS = [
|
5
|
+
:sunionstore,
|
6
|
+
:srem,
|
7
|
+
:spop,
|
8
|
+
:smove,
|
5
9
|
:setrange,
|
6
10
|
:setnx,
|
7
11
|
:setbit,
|
@@ -45,6 +49,10 @@ module Redsquare
|
|
45
49
|
]
|
46
50
|
|
47
51
|
GET_COMMANDS = [
|
52
|
+
:sunion,
|
53
|
+
:srandmember,
|
54
|
+
:smembers,
|
55
|
+
:sismember,
|
48
56
|
:sinter,
|
49
57
|
:sdiff,
|
50
58
|
:scard,
|
@@ -66,15 +74,14 @@ module Redsquare
|
|
66
74
|
:getbit,
|
67
75
|
:get,
|
68
76
|
:exists,
|
69
|
-
:dump,
|
70
77
|
:dbsize
|
71
78
|
]
|
72
79
|
|
73
80
|
POST_COMMANDS.each do |command|
|
74
|
-
post "/#{command}
|
81
|
+
post "/#{command}" do
|
75
82
|
content_type :json
|
76
|
-
args = params[:
|
77
|
-
val =
|
83
|
+
args = params[:args].map { |a| try_to_i a }
|
84
|
+
val = Config.redis.send command, *args
|
78
85
|
{ result: val }.to_json
|
79
86
|
end
|
80
87
|
end
|
@@ -82,11 +89,16 @@ module Redsquare
|
|
82
89
|
GET_COMMANDS.each do |command|
|
83
90
|
get "/#{command}/?*" do
|
84
91
|
content_type :json
|
85
|
-
args = params[:splat][0].split("/")
|
86
|
-
val =
|
92
|
+
args = params[:splat][0].split("/").map { |a| try_to_i a }
|
93
|
+
val = Config.redis.send command, *args
|
87
94
|
{ result: val }.to_json
|
88
95
|
end
|
89
96
|
end
|
90
97
|
|
98
|
+
def try_to_i(str)
|
99
|
+
is_int = str.to_i.to_s == str
|
100
|
+
is_int ? str.to_i : str
|
101
|
+
end
|
102
|
+
|
91
103
|
end
|
92
104
|
end
|
data/lib/redsquare/version.rb
CHANGED
data/lib/redsquare.rb
CHANGED
data/redsquare.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = "redsquare"
|
9
9
|
spec.version = Redsquare::VERSION
|
10
10
|
spec.authors = ["JC Grubbs"]
|
11
|
-
spec.email = ["jc
|
12
|
-
spec.description = %q{
|
13
|
-
spec.summary = %q{
|
11
|
+
spec.email = ["jc@devmynd.com"]
|
12
|
+
spec.description = %q{A mountable/standalone JSON interface to Redis.}
|
13
|
+
spec.summary = %q{A mountable/standalone JSON interface to Redis.}
|
14
14
|
spec.homepage = "http://github.com/thegrubbsian/redsquare"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -27,4 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency "rake"
|
28
28
|
spec.add_development_dependency "rspec"
|
29
29
|
spec.add_development_dependency "pry"
|
30
|
+
spec.add_development_dependency "rack-test"
|
31
|
+
spec.add_development_dependency "fakeredis"
|
32
|
+
|
30
33
|
end
|
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Redsquare::App do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
def app
|
7
|
+
Redsquare::App
|
8
|
+
end
|
9
|
+
|
10
|
+
def result
|
11
|
+
JSON.parse(last_response.body)["result"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def redis
|
15
|
+
Redis.current
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "GET commands" do
|
19
|
+
|
20
|
+
before do
|
21
|
+
|
22
|
+
# String
|
23
|
+
redis.set "string_a", "bar"
|
24
|
+
redis.set "string_b", "baz"
|
25
|
+
|
26
|
+
# Sets
|
27
|
+
redis.sadd "set_a", "a"
|
28
|
+
redis.sadd "set_a", "b"
|
29
|
+
redis.sadd "set_a", "c"
|
30
|
+
|
31
|
+
redis.sadd "set_b", "b"
|
32
|
+
redis.sadd "set_b", "c"
|
33
|
+
redis.sadd "set_b", "d"
|
34
|
+
|
35
|
+
# Lists
|
36
|
+
redis.rpush "list_a", "a"
|
37
|
+
redis.rpush "list_a", "b"
|
38
|
+
redis.rpush "list_a", "c"
|
39
|
+
|
40
|
+
redis.rpush "list_b", "b"
|
41
|
+
redis.rpush "list_b", "c"
|
42
|
+
redis.rpush "list_b", "d"
|
43
|
+
|
44
|
+
# Expiring key
|
45
|
+
redis.set "expire", "foo"
|
46
|
+
redis.expireat "expireat", 1555555555005
|
47
|
+
|
48
|
+
# Hashes
|
49
|
+
redis.hset "hash_a", "a", 1
|
50
|
+
redis.hset "hash_a", "b", 2.00
|
51
|
+
redis.hset "hash_a", "c", "foobar"
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "returns the correct response for" do
|
55
|
+
|
56
|
+
it "sinter" do
|
57
|
+
get "/sinter/set_a/set_b"
|
58
|
+
expect(result).to eq ["b", "c"]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "sdiff" do
|
62
|
+
get "/sdiff/set_a/set_b"
|
63
|
+
expect(result).to eq ["a"]
|
64
|
+
get "/sdiff/set_b/set_a"
|
65
|
+
expect(result).to eq ["d"]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "scard" do
|
69
|
+
get "/scard/set_a"
|
70
|
+
expect(result).to eq 3
|
71
|
+
end
|
72
|
+
|
73
|
+
it "randomkey" do
|
74
|
+
get "/randomkey"
|
75
|
+
expect(result).to_not be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "mget" do
|
79
|
+
get "/mget/string_a/string_b"
|
80
|
+
expect(result).to eq ["bar", "baz"]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "lrange" do
|
84
|
+
get "/lrange/list_a/0/1"
|
85
|
+
expect(result).to eq ["a", "b"]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "llen" do
|
89
|
+
get "/llen/list_a"
|
90
|
+
expect(result).to eq 3
|
91
|
+
end
|
92
|
+
|
93
|
+
it "lindex" do
|
94
|
+
get "/lindex/list_a/1"
|
95
|
+
expect(result).to eq "b"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "keys" do
|
99
|
+
get "/keys"
|
100
|
+
expect(result).to eq Redis.current.keys
|
101
|
+
end
|
102
|
+
|
103
|
+
it "hvals" do
|
104
|
+
get "/hvals/hash_a"
|
105
|
+
expect(result).to eq ["1", "2.0", "foobar"]
|
106
|
+
end
|
107
|
+
|
108
|
+
it "hmget" do
|
109
|
+
get "/hmget/hash_a/a/c"
|
110
|
+
expect(result).to eq ["1", "foobar"]
|
111
|
+
end
|
112
|
+
|
113
|
+
it "hlen" do
|
114
|
+
get "/hlen/hash_a"
|
115
|
+
expect(result).to eq 3
|
116
|
+
end
|
117
|
+
|
118
|
+
it "hkeys" do
|
119
|
+
get "/hkeys/hash_a"
|
120
|
+
expect(result).to eq ["a", "b", "c"]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "hgetall" do
|
124
|
+
get "/hgetall/hash_a"
|
125
|
+
expect(result).to eq({ "a" => "1", "b" => "2.0", "c" => "foobar" })
|
126
|
+
end
|
127
|
+
|
128
|
+
it "hget" do
|
129
|
+
get "/hget/hash_a/a"
|
130
|
+
expect(result).to eq "1"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "hexists" do
|
134
|
+
get "/hexists/hash_a/c"
|
135
|
+
expect(result).to be_true
|
136
|
+
end
|
137
|
+
|
138
|
+
it "getrange" do
|
139
|
+
get "/getrange/string_a/0/1"
|
140
|
+
expect(result).to eq "ba"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "get" do
|
144
|
+
get "/get/string_a"
|
145
|
+
expect(result).to eq "bar"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "exists" do
|
149
|
+
get "/get/string_a"
|
150
|
+
expect(result).to be_true
|
151
|
+
end
|
152
|
+
|
153
|
+
it "dbsize" do
|
154
|
+
get "/dbsize"
|
155
|
+
expect(result).to eq 8
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "POST commands" do
|
163
|
+
|
164
|
+
describe "returns the correct response for" do
|
165
|
+
|
166
|
+
it "setrange" do
|
167
|
+
redis.set "string_a", "Hello World"
|
168
|
+
post "/setrange", args: ["string_a", 6, "Redis"]
|
169
|
+
expect(redis.get "string_a").to eq "Hello Redis"
|
170
|
+
end
|
171
|
+
|
172
|
+
it "setnx" do
|
173
|
+
post "/setnx", args: ["bar", "baz"]
|
174
|
+
expect(redis.get "bar").to eq "baz"
|
175
|
+
end
|
176
|
+
|
177
|
+
it "set" do
|
178
|
+
post "/set", args: ["string_a", "foo"]
|
179
|
+
expect(redis.get "string_a").to eq "foo"
|
180
|
+
end
|
181
|
+
|
182
|
+
it "sdiffstore" do
|
183
|
+
redis.sadd "list_a", "a"
|
184
|
+
redis.sadd "list_a", "b"
|
185
|
+
redis.sadd "list_a", "c"
|
186
|
+
redis.sadd "list_b", "b"
|
187
|
+
redis.sadd "list_b", "c"
|
188
|
+
redis.sadd "list_b", "d"
|
189
|
+
post "/sdiffstore", args: ["list_c", "list_a", "list_b"]
|
190
|
+
expect(redis.smembers "list_c").to eq ["a"]
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redsquare
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JC Grubbs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -108,9 +108,37 @@ dependencies:
|
|
108
108
|
- - '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
-
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rack-test
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: fakeredis
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: A mountable/standalone JSON interface to Redis.
|
112
140
|
email:
|
113
|
-
- jc
|
141
|
+
- jc@devmynd.com
|
114
142
|
executables:
|
115
143
|
- redsquare
|
116
144
|
extensions: []
|
@@ -123,10 +151,12 @@ files:
|
|
123
151
|
- Rakefile
|
124
152
|
- bin/redsquare
|
125
153
|
- lib/redsquare.rb
|
126
|
-
- lib/redsquare/
|
127
|
-
- lib/redsquare/
|
154
|
+
- lib/redsquare/app.rb
|
155
|
+
- lib/redsquare/config.rb
|
128
156
|
- lib/redsquare/version.rb
|
129
157
|
- redsquare.gemspec
|
158
|
+
- spec/app_spec.rb
|
159
|
+
- spec/spec_helper.rb
|
130
160
|
homepage: http://github.com/thegrubbsian/redsquare
|
131
161
|
licenses:
|
132
162
|
- MIT
|
@@ -150,5 +180,7 @@ rubyforge_project:
|
|
150
180
|
rubygems_version: 2.0.2
|
151
181
|
signing_key:
|
152
182
|
specification_version: 4
|
153
|
-
summary:
|
154
|
-
test_files:
|
183
|
+
summary: A mountable/standalone JSON interface to Redis.
|
184
|
+
test_files:
|
185
|
+
- spec/app_spec.rb
|
186
|
+
- spec/spec_helper.rb
|