wolverine 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.travis.yml +10 -0
- data/README.md +6 -7
- data/Rakefile +15 -1
- data/TODO +2 -5
- data/lib/wolverine.rb +26 -6
- data/lib/wolverine/configuration.rb +22 -1
- data/lib/wolverine/lua_error.rb +26 -12
- data/lib/wolverine/path_component.rb +18 -1
- data/lib/wolverine/script.rb +40 -7
- data/lib/wolverine/version.rb +1 -1
- data/test/integration/wolverine_integration_test.rb +1 -1
- data/test/wolverine/configuration_test.rb +12 -1
- data/test/wolverine/path_component_test.rb +2 -2
- data/test/wolverine/script_test.rb +29 -31
- data/test/wolverine_test.rb +1 -1
- data/wolverine.gemspec +5 -3
- metadata +35 -11
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
# Wolverine
|
1
|
+
# Wolverine [![Build Status](https://secure.travis-ci.org/burke/wolverine.png)](http://travis-ci.org/burke/wolverine) [![Dependency Status](https://gemnasium.com/Shopify/wolverine.png)](https://gemnasium.com/Shopify/wolverine)
|
2
2
|
|
3
3
|
Wolverine is a simple library to allow you to manage and run redis server-side lua scripts from a rails app, or other ruby code.
|
4
4
|
|
5
|
-
|
5
|
+
Redis versions 2.6 and up allow lua scripts to be run on the server that execute atomically and very quickly.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
This is really, really cool.
|
7
|
+
This is *extremely* useful.
|
10
8
|
|
11
9
|
Wolverine is a wrapper around that functionality, to package it up in a format more familiar to a Rails codebase.
|
12
10
|
|
@@ -53,8 +51,9 @@ Available configuration options:
|
|
53
51
|
|
54
52
|
* `Wolverine.config.redis` (default `Redis.new`)
|
55
53
|
* `Wolverine.config.script_path` (default `Rails.root + 'app/wolverine'`)
|
54
|
+
* `Wolverine.config.instrumentation` (default none)
|
56
55
|
|
57
|
-
If you want to override one or
|
56
|
+
If you want to override one or more of these, doing so in an initializer is recommended but not required. See the [full documentation](http://shopify.github.com/wolverine/Wolverine/Configuration.html) for more details.
|
58
57
|
|
59
58
|
## More information
|
60
59
|
|
@@ -62,7 +61,7 @@ For more information on scripting redis with lua, refer to redis' excellent docu
|
|
62
61
|
|
63
62
|
## License
|
64
63
|
|
65
|
-
Copyright (C) 2012 Shopify
|
64
|
+
Copyright (C) 2012 [Shopify](http://shopify.com) by [Burke Libbey](http://burkelibbey.org)
|
66
65
|
|
67
66
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
68
67
|
|
data/Rakefile
CHANGED
@@ -5,4 +5,18 @@ Rake::TestTask.new do |t|
|
|
5
5
|
t.pattern = "test/**/*_test.rb"
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
require 'yard'
|
9
|
+
require 'yard/rake/yardoc_task'
|
10
|
+
YARD::Rake::YardocTask.new do |yardoc|
|
11
|
+
yardoc.options = ['--verbose']
|
12
|
+
# yardoc.files = [
|
13
|
+
# 'lib/**/*.rb', 'README.md', 'CHANGELOG.md', 'LICENSE'
|
14
|
+
# ]
|
15
|
+
end
|
16
|
+
|
17
|
+
task :docs do
|
18
|
+
Rake::Task['yard'].invoke
|
19
|
+
system("cd doc && git add . && git commit -am 'Regenerated docs' && git push origin gh-pages")
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :test
|
data/TODO
CHANGED
@@ -1,5 +1,2 @@
|
|
1
|
-
-
|
2
|
-
-
|
3
|
-
- clean up error handling method
|
4
|
-
- Re-evaluate what actually needs to be exposed as public
|
5
|
-
- Think of more TODO items
|
1
|
+
- cache methods on Wolverine, rather than using method_missing all the time
|
2
|
+
- better tests around error handling and stacktrace trimming
|
data/lib/wolverine.rb
CHANGED
@@ -8,26 +8,46 @@ require 'wolverine/path_component'
|
|
8
8
|
require 'wolverine/lua_error'
|
9
9
|
|
10
10
|
module Wolverine
|
11
|
+
# Returns the configuration object for reading and writing
|
12
|
+
# configuration values.
|
13
|
+
#
|
14
|
+
# @return [Wolverine::Configuration] the configuration object
|
11
15
|
def self.config
|
12
16
|
@config ||= Configuration.new
|
13
17
|
end
|
14
18
|
|
19
|
+
# Provides access to the redis connection currently in use by Wolverine.
|
20
|
+
#
|
21
|
+
# @return [Redis] the redis connection used by Wolverine
|
15
22
|
def self.redis
|
16
23
|
config.redis
|
17
24
|
end
|
18
25
|
|
26
|
+
# Resets all the scripts cached by Wolverine. Scripts are lazy-loaded and
|
27
|
+
# cached in-memory, so if a file changes on disk, it will be necessary to
|
28
|
+
# manually reset the cache using +reset!+.
|
29
|
+
#
|
30
|
+
# @return [void]
|
19
31
|
def self.reset!
|
20
32
|
@root_directory = nil
|
21
33
|
end
|
22
34
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
35
|
+
# Used to handle dynamic accesses to scripts. Successful lookups will be
|
36
|
+
# cached on the {PathComponent} object. See {PathComponent#method_missing}
|
37
|
+
# for more detail on how this works.
|
38
|
+
#
|
39
|
+
# @return [PathComponent, Object] a PathComponent if the method maps to a
|
40
|
+
# directory, or an execution result if the the method maps to a lua file.
|
27
41
|
def self.method_missing sym, *args
|
28
|
-
root_directory.send(sym, *args)
|
42
|
+
root_directory.send(sym, *args)
|
29
43
|
rescue PathComponent::MissingTemplate
|
30
|
-
super
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.root_directory
|
50
|
+
@root_directory ||= PathComponent.new(config.script_path)
|
31
51
|
end
|
32
52
|
|
33
53
|
end
|
@@ -1,9 +1,30 @@
|
|
1
1
|
module Wolverine
|
2
|
-
class Configuration < Struct.new(:redis, :script_path)
|
2
|
+
class Configuration < Struct.new(:redis, :script_path, :instrumentation)
|
3
|
+
|
4
|
+
# @return [Redis] the redis connection actively in use by Wolverine
|
3
5
|
def redis
|
4
6
|
super || @redis ||= Redis.new
|
5
7
|
end
|
6
8
|
|
9
|
+
# Wolverine.config.instrumentation can be used to specify a callback to
|
10
|
+
# fire with the runtime of each script. This can be useful for analyzing
|
11
|
+
# scripts to make sure they aren't running for an unreasonable amount of
|
12
|
+
# time.
|
13
|
+
#
|
14
|
+
# The proc will receive three parameters:
|
15
|
+
#
|
16
|
+
# * +script_name+: A unique identifier for the script, based on its
|
17
|
+
# location in the file system
|
18
|
+
# * +runtime+: A float, the total execution time of the script
|
19
|
+
# * +eval_type+: Either +eval+ or +evalsha+, the method used to run
|
20
|
+
# the script
|
21
|
+
# @return [#call] the proc or other callable to be triggered on completion
|
22
|
+
# of a script.
|
23
|
+
def instrumentation
|
24
|
+
super || @instrumentation ||= proc { |script_name, runtime, eval_type| nil }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Pathname] the path wolverine will check for scripts
|
7
28
|
def script_path
|
8
29
|
super || @script_path ||= Rails.root + 'app/wolverine'
|
9
30
|
end
|
data/lib/wolverine/lua_error.rb
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
module Wolverine
|
2
|
+
# Reformats errors raised by redis representing failures while executing
|
3
|
+
# a lua script. The default errors have confusing messages and backtraces,
|
4
|
+
# and a type of +RuntimeError+. This class improves the message and
|
5
|
+
# modifies the backtrace to include the lua script itself in a reasonable
|
6
|
+
# way.
|
2
7
|
class LuaError < StandardError
|
3
8
|
PATTERN = /ERR Error (compiling|running) script \(.*?\): \[.*?\]:(\d+): (.*)/
|
4
9
|
WOLVERINE_LIB_PATH = File.expand_path('../../', __FILE__)
|
5
10
|
|
6
|
-
|
7
|
-
|
11
|
+
# Is this error one that should be reformatted?
|
12
|
+
#
|
13
|
+
# @param error [StandardError] the original error raised by redis
|
14
|
+
# @return [Boolean] is this an error that should be reformatted?
|
15
|
+
def self.intercepts? error
|
16
|
+
error.message =~ PATTERN
|
8
17
|
end
|
9
18
|
|
10
|
-
|
11
|
-
|
19
|
+
# Initialize a new {LuaError} from an existing redis error, adjusting
|
20
|
+
# the message and backtrace in the process.
|
21
|
+
#
|
22
|
+
# @param error [StandardError] the original error raised by redis
|
23
|
+
# @param file [Pathname] full path to the lua file the error ocurred in
|
24
|
+
def initialize error, file
|
12
25
|
@error = error
|
13
26
|
@file = file
|
14
27
|
|
15
|
-
error.message =~ PATTERN
|
28
|
+
@error.message =~ PATTERN
|
16
29
|
stage, line_number, message = $1, $2, $3
|
17
30
|
|
18
|
-
|
19
|
-
|
20
|
-
set_backtrace generate_backtrace(file, line_number)
|
31
|
+
super message
|
32
|
+
set_backtrace generate_backtrace file, line_number
|
21
33
|
end
|
22
34
|
|
35
|
+
private
|
36
|
+
|
23
37
|
def generate_backtrace(file, line_number)
|
24
|
-
pre_wolverine = backtrace_before_entering_wolverine(error.backtrace)
|
25
|
-
index_of_first_wolverine_line = (error.backtrace.size - pre_wolverine.size - 1)
|
26
|
-
pre_wolverine.unshift(error.backtrace[index_of_first_wolverine_line])
|
38
|
+
pre_wolverine = backtrace_before_entering_wolverine(@error.backtrace)
|
39
|
+
index_of_first_wolverine_line = (@error.backtrace.size - pre_wolverine.size - 1)
|
40
|
+
pre_wolverine.unshift(@error.backtrace[index_of_first_wolverine_line])
|
27
41
|
pre_wolverine.unshift("#{file}:#{line_number}")
|
28
42
|
pre_wolverine
|
29
43
|
end
|
@@ -38,4 +52,4 @@ module Wolverine
|
|
38
52
|
|
39
53
|
end
|
40
54
|
|
41
|
-
end
|
55
|
+
end
|
@@ -1,11 +1,28 @@
|
|
1
1
|
module Wolverine
|
2
|
+
# A {PathComponent} represents either the +Wolverine.config.script_path+
|
3
|
+
# directory, or a subdirectory of it. Calling (nearly) any method on it will
|
4
|
+
# cause it to look in the filesystem at the location it refers to for a file
|
5
|
+
# or directory matching the method name. These results are cached.
|
6
|
+
#
|
7
|
+
# Calling a method that maps to a directory will return a new {PathComponent}
|
8
|
+
# with a +path+ referring to that directory.
|
9
|
+
#
|
10
|
+
# Calling a method that maps to a file (with +'.lua'+ automatically appended
|
11
|
+
# to the name) will load the file via {Script} and call it with the
|
12
|
+
# arugments passed, returning the result ({method_missing}).
|
2
13
|
class PathComponent
|
3
14
|
class MissingTemplate < StandardError ; end
|
4
15
|
|
16
|
+
# @param path [Pathname] full path to the current file or directory
|
5
17
|
def initialize path
|
6
18
|
@path = path
|
7
19
|
end
|
8
20
|
|
21
|
+
# @param sym [Symbol] the file or directory to look up and execute
|
22
|
+
# @param args [*Objects] arguments to pass to the {Script}, if +sym+ resolves to a lua file
|
23
|
+
# @return [PathComponent, Object] A new, nested {PathComponent} if +sym+ resolves to
|
24
|
+
# a directory, or an execution result if it resolves to a file.
|
25
|
+
# @raise [MissingTemplate] if +sym+ maps to neither a directory or a file
|
9
26
|
def method_missing sym, *args
|
10
27
|
create_method sym, *args
|
11
28
|
send sym, *args
|
@@ -50,4 +67,4 @@ module Wolverine
|
|
50
67
|
|
51
68
|
end
|
52
69
|
|
53
|
-
end
|
70
|
+
end
|
data/lib/wolverine/script.rb
CHANGED
@@ -1,15 +1,33 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'benchmark'
|
1
3
|
require 'digest/sha1'
|
2
4
|
|
3
5
|
module Wolverine
|
4
|
-
|
6
|
+
# {Script} represents a lua script in the filesystem. It loads the script
|
7
|
+
# from disk and handles talking to redis to execute it. Error handling
|
8
|
+
# is handled by {LuaError}.
|
5
9
|
class Script
|
6
|
-
|
10
|
+
|
11
|
+
# Loads the script file from disk and calculates its +SHA1+ sum.
|
12
|
+
#
|
13
|
+
# @param file [Pathname] the full path to the indicated file
|
7
14
|
def initialize file
|
8
|
-
@file = file
|
15
|
+
@file = Pathname.new(file)
|
9
16
|
@content = load_lua file
|
10
17
|
@digest = Digest::SHA1.hexdigest @content
|
11
18
|
end
|
12
19
|
|
20
|
+
# Passes the script and supplied arguments to redis for evaulation.
|
21
|
+
# It first attempts to use a script redis has already cached by using
|
22
|
+
# the +EVALSHA+ command, but falls back to providing the full script
|
23
|
+
# text via +EVAL+ if redis has not seen this script before. Future
|
24
|
+
# invocations will then use +EVALSHA+ without erroring.
|
25
|
+
#
|
26
|
+
# @param redis [Redis] the redis connection to run against
|
27
|
+
# @param args [*Objects] the arguments to the script
|
28
|
+
# @return [Object] the value passed back by redis after script execution
|
29
|
+
# @raise [LuaError] if the script failed to compile of encountered a
|
30
|
+
# runtime error
|
13
31
|
def call redis, *args
|
14
32
|
begin
|
15
33
|
run_evalsha redis, *args
|
@@ -17,8 +35,8 @@ module Wolverine
|
|
17
35
|
e.message =~ /NOSCRIPT/ ? run_eval(redis, *args) : raise
|
18
36
|
end
|
19
37
|
rescue => e
|
20
|
-
if LuaError.intercepts?(e)
|
21
|
-
raise LuaError.new(e, file)
|
38
|
+
if LuaError.intercepts?(e)
|
39
|
+
raise LuaError.new(e, @file)
|
22
40
|
else
|
23
41
|
raise
|
24
42
|
end
|
@@ -27,11 +45,26 @@ module Wolverine
|
|
27
45
|
private
|
28
46
|
|
29
47
|
def run_evalsha redis, *args
|
30
|
-
|
48
|
+
instrument :evalsha do
|
49
|
+
redis.evalsha @digest, args.size, *args
|
50
|
+
end
|
31
51
|
end
|
32
52
|
|
33
53
|
def run_eval redis, *args
|
34
|
-
|
54
|
+
instrument :eval do
|
55
|
+
redis.eval @content, args.size, *args
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def instrument eval_type
|
60
|
+
ret = nil
|
61
|
+
runtime = Benchmark.realtime { ret = yield }
|
62
|
+
Wolverine.config.instrumentation.call relative_path.to_s, runtime, eval_type
|
63
|
+
ret
|
64
|
+
end
|
65
|
+
|
66
|
+
def relative_path
|
67
|
+
path = @file.relative_path_from(Wolverine.config.script_path)
|
35
68
|
end
|
36
69
|
|
37
70
|
def load_lua file
|
data/lib/wolverine/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require File.join(File.expand_path('../../test_helper', __FILE__))
|
2
2
|
require 'pathname'
|
3
3
|
|
4
4
|
module Rails
|
@@ -19,6 +19,11 @@ module Wolverine
|
|
19
19
|
assert_equal Pathname.new('foo/app/wolverine'), actual
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_default_instrumentation
|
23
|
+
config = Wolverine::Configuration.new
|
24
|
+
assert_equal nil, config.instrumentation.call(1, 2, 3)
|
25
|
+
end
|
26
|
+
|
22
27
|
def test_setting_redis
|
23
28
|
config = Wolverine::Configuration.new
|
24
29
|
config.redis = :foo
|
@@ -31,5 +36,11 @@ module Wolverine
|
|
31
36
|
assert_equal :foo, config.script_path
|
32
37
|
end
|
33
38
|
|
39
|
+
def test_setting_instrumentation
|
40
|
+
config = Wolverine::Configuration.new
|
41
|
+
config.instrumentation = proc { |a, b, c| :omg }
|
42
|
+
assert_equal :omg, config.instrumentation.call(1,2,3)
|
43
|
+
end
|
44
|
+
|
34
45
|
end
|
35
46
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require File.join(File.expand_path('../../test_helper', __FILE__))
|
2
2
|
require 'digest/sha1'
|
3
3
|
|
4
4
|
module Wolverine
|
@@ -7,49 +7,47 @@ module Wolverine
|
|
7
7
|
DIGEST = Digest::SHA1.hexdigest(CONTENT)
|
8
8
|
|
9
9
|
def setup
|
10
|
-
|
10
|
+
base = Pathname.new('/a/b/c/d')
|
11
|
+
Wolverine.config.script_path = base
|
12
|
+
Wolverine::Script.any_instance.stubs(:load_lua => CONTENT)
|
11
13
|
end
|
12
14
|
|
13
|
-
def
|
14
|
-
|
15
|
+
def teardown
|
16
|
+
Wolverine.config.instrumentation = proc{}
|
15
17
|
end
|
16
18
|
|
17
|
-
def
|
18
|
-
|
19
|
-
file = Pathname.new('/a/b/c/d/e/file1.lua')
|
20
|
-
Wolverine.config.script_path = base
|
21
|
-
begin
|
22
|
-
script = Wolverine::Script.new(file)
|
23
|
-
script.instance_variable_set("@content", "asdfasdfasdf+31f")
|
24
|
-
script.instance_variable_set("@digest", "79437f5edda13f9c1669b978dd7a9066dd2059f1")
|
25
|
-
script.call(Redis.new)
|
26
|
-
rescue Wolverine::LuaError => e
|
27
|
-
assert_equal "'=' expected near '+'", e.message
|
28
|
-
assert_equal "/a/b/c/d/e/file1.lua:1", e.backtrace.first
|
29
|
-
assert_match /script.rb/, e.backtrace[1]
|
30
|
-
end
|
19
|
+
def script
|
20
|
+
@script ||= Wolverine::Script.new('/a/b/c/d/e/file1.lua')
|
31
21
|
end
|
32
22
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
Wolverine.config.script_path = base
|
23
|
+
def test_error
|
24
|
+
redis = stub
|
25
|
+
redis.expects(:evalsha).raises(%q{ERR Error running script (call to f_178d75adaa46af3d8237cfd067c9fdff7b9d504f): [string "func definition"]:1: attempt to compare nil with number})
|
37
26
|
begin
|
38
|
-
script
|
39
|
-
script.instance_variable_set("@content", "return nil > 3")
|
40
|
-
script.instance_variable_set("@digest", "39437f5edda13f9c1669b978dd7a9066dd2059f1")
|
41
|
-
script.call(Redis.new)
|
27
|
+
script.call(redis)
|
42
28
|
rescue Wolverine::LuaError => e
|
43
|
-
assert_equal "attempt to compare
|
29
|
+
assert_equal "attempt to compare nil with number", e.message
|
44
30
|
assert_equal "/a/b/c/d/e/file1.lua:1", e.backtrace.first
|
45
31
|
assert_match /script.rb/, e.backtrace[1]
|
46
32
|
end
|
47
33
|
end
|
48
34
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
35
|
+
def test_instrumentation
|
36
|
+
callback = Object.new
|
37
|
+
tc = self
|
38
|
+
meta = class << callback ; self ; end
|
39
|
+
meta.send(:define_method, :call) { |a, b, c|
|
40
|
+
tc.assert_equal "e/file1.lua", a
|
41
|
+
tc.assert_operator b, :<, 1
|
42
|
+
tc.assert_equal :evalsha, c
|
43
|
+
}
|
44
|
+
Wolverine.config.instrumentation = callback
|
45
|
+
redis = Class.new do
|
46
|
+
define_method(:evalsha) do |digest, size, *args|
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
script.call(redis.new, :a, :b)
|
53
51
|
end
|
54
52
|
|
55
53
|
def test_call_with_cache_hit
|
data/test/wolverine_test.rb
CHANGED
data/wolverine.gemspec
CHANGED
@@ -18,7 +18,9 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency
|
22
|
-
s.add_development_dependency 'mocha'
|
23
|
-
s.add_development_dependency 'minitest'
|
21
|
+
s.add_runtime_dependency 'redis', '~> 2.2.2'
|
22
|
+
s.add_development_dependency 'mocha', '~> 0.10.5'
|
23
|
+
s.add_development_dependency 'minitest', '~> 2.11.3'
|
24
|
+
s.add_development_dependency 'rake'
|
25
|
+
s.add_development_dependency 'yard'
|
24
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wolverine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,44 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70155163744540 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 2.2.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70155163744540
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mocha
|
27
|
-
requirement: &
|
27
|
+
requirement: &70155163743720 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.10.5
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70155163743720
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: minitest
|
38
|
+
requirement: &70155163743080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.11.3
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70155163743080
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &70155163742680 !ruby/object:Gem::Requirement
|
28
50
|
none: false
|
29
51
|
requirements:
|
30
52
|
- - ! '>='
|
@@ -32,10 +54,10 @@ dependencies:
|
|
32
54
|
version: '0'
|
33
55
|
type: :development
|
34
56
|
prerelease: false
|
35
|
-
version_requirements: *
|
57
|
+
version_requirements: *70155163742680
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
59
|
+
name: yard
|
60
|
+
requirement: &70155163742180 !ruby/object:Gem::Requirement
|
39
61
|
none: false
|
40
62
|
requirements:
|
41
63
|
- - ! '>='
|
@@ -43,7 +65,7 @@ dependencies:
|
|
43
65
|
version: '0'
|
44
66
|
type: :development
|
45
67
|
prerelease: false
|
46
|
-
version_requirements: *
|
68
|
+
version_requirements: *70155163742180
|
47
69
|
description: Wolverine provides a simple way to run server-side redis scripts from
|
48
70
|
a rails app
|
49
71
|
email:
|
@@ -53,6 +75,7 @@ extensions: []
|
|
53
75
|
extra_rdoc_files: []
|
54
76
|
files:
|
55
77
|
- .gitignore
|
78
|
+
- .travis.yml
|
56
79
|
- Gemfile
|
57
80
|
- LICENSE
|
58
81
|
- README.md
|
@@ -109,3 +132,4 @@ test_files:
|
|
109
132
|
- test/wolverine/path_component_test.rb
|
110
133
|
- test/wolverine/script_test.rb
|
111
134
|
- test/wolverine_test.rb
|
135
|
+
has_rdoc:
|