resque-status 0.2.4 → 0.3.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.
- data/Gemfile +8 -0
- data/Gemfile.lock +51 -0
- data/README.rdoc +30 -18
- data/Rakefile +6 -4
- data/examples/sleep_job.rb +9 -8
- data/init.rb +1 -1
- data/lib/resque-status.rb +1 -0
- data/lib/resque/job_with_status.rb +1 -198
- data/lib/resque/plugins/status.rb +213 -0
- data/lib/resque/plugins/status/hash.rb +242 -0
- data/lib/resque/server/views/status.erb +2 -2
- data/lib/resque/server/views/statuses.erb +10 -7
- data/lib/resque/status.rb +2 -237
- data/lib/resque/status_server.rb +23 -18
- data/resque-status.gemspec +34 -11
- data/test/test_helper.rb +16 -7
- data/test/{test_resque-job_with_status.rb → test_resque_plugins_status.rb} +94 -10
- data/test/test_resque_plugins_status_hash.rb +153 -0
- metadata +89 -20
- data/test/test_resque-status.rb +0 -153
@@ -1,7 +1,7 @@
|
|
1
1
|
<%= status_view :status_styles, :layout => false %>
|
2
2
|
|
3
3
|
<h1 class='wi'>Statuses: <%= @status.uuid %>/<%= @status.name %></h1>
|
4
|
-
<p class='intro'>Viewing a specific job created with
|
4
|
+
<p class='intro'>Viewing a specific job created with Resque::Plugins::Status. <a href="<%= u(:statuses) %>">Return to the list of statuses</a></p>
|
5
5
|
|
6
6
|
<div class="status-holder" rel="<%= @status.status %>" id="status_<%= @status.uuid %>">
|
7
7
|
<div class="status-progress">
|
@@ -29,7 +29,7 @@
|
|
29
29
|
var pct = json.pct_complete + "%";
|
30
30
|
}
|
31
31
|
$status.find('.status-progress-bar').animate({width: pct});
|
32
|
-
$status.find('.status-progress p').text(pct)
|
32
|
+
$status.find('.status-progress p').text(pct)
|
33
33
|
if (json.message) {
|
34
34
|
$status.find('.status-message').html(json.message)
|
35
35
|
}
|
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
<h1 class='wi'>Statuses</h1>
|
4
4
|
<%unless @statuses.empty?%>
|
5
|
-
|
6
|
-
<input type='submit' name='' value='Clear Statuses' />
|
5
|
+
<form method="POST" action="<%= u(:statuses) %>/clear" class='clear-failed'>
|
6
|
+
<input type='submit' name='' value='Clear Statuses' onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
|
7
|
+
</form>
|
8
|
+
<form method="POST" action="<%= u(:statuses) %>/clear/completed" class='clear-failed'>
|
9
|
+
<input type='submit' name='' value='Clear Completed Statuses' onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
|
7
10
|
</form>
|
8
11
|
<%end%>
|
9
|
-
<p class='intro'>These are recent jobs created with the
|
12
|
+
<p class='intro'>These are recent jobs created with the Resque::Plugins::Status class</p>
|
10
13
|
<table>
|
11
14
|
<tr>
|
12
15
|
<th>ID</th>
|
@@ -32,7 +35,7 @@
|
|
32
35
|
<td><% if status.killable? %><a href="<%= u(:statuses) %>/<%= status.uuid %>/kill" class="kill">Kill</a><% end %></td>
|
33
36
|
</tr>
|
34
37
|
<% end %>
|
35
|
-
<% else %>
|
38
|
+
<% else %>
|
36
39
|
<tr>
|
37
40
|
<td colspan="7" class='no-data'>No Statuses right now...</td>
|
38
41
|
</tr>
|
@@ -40,14 +43,14 @@
|
|
40
43
|
</table>
|
41
44
|
|
42
45
|
<% unless @statuses.empty? %>
|
43
|
-
|
46
|
+
<%= partial :next_more, :start => @start, :size => @size %>
|
44
47
|
<% end %>
|
45
48
|
|
46
49
|
<%= status_poll(@start) %>
|
47
50
|
|
48
51
|
<script type="text/javascript" charset="utf-8">
|
49
52
|
jQuery(function($) {
|
50
|
-
|
53
|
+
|
51
54
|
$('a.kill').click(function(e) {
|
52
55
|
e.preventDefault();
|
53
56
|
var $link = $(this),
|
@@ -66,6 +69,6 @@
|
|
66
69
|
return false
|
67
70
|
}
|
68
71
|
});
|
69
|
-
|
72
|
+
|
70
73
|
});
|
71
74
|
</script>
|
data/lib/resque/status.rb
CHANGED
@@ -2,240 +2,5 @@ require 'resque'
|
|
2
2
|
require 'redisk'
|
3
3
|
require 'uuid'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
# the common status attributes. It also has a number of class methods for
|
8
|
-
# creating/updating/retrieving status objects from Redis
|
9
|
-
class Status < Hash
|
10
|
-
VERSION = '0.2.4'
|
11
|
-
|
12
|
-
extend Resque::Helpers
|
13
|
-
|
14
|
-
# Create a status, generating a new UUID, passing the message to the status
|
15
|
-
# Returns the UUID of the new status.
|
16
|
-
def self.create(*messages)
|
17
|
-
uuid = generate_uuid
|
18
|
-
set(uuid, *messages)
|
19
|
-
redis.zadd(set_key, Time.now.to_i, uuid)
|
20
|
-
redis.zremrangebyscore(set_key, 0, Time.now.to_i - @expire_in) if @expire_in
|
21
|
-
uuid
|
22
|
-
end
|
23
|
-
|
24
|
-
# Get a status by UUID. Returns a Resque::Status
|
25
|
-
def self.get(uuid)
|
26
|
-
val = redis.get(status_key(uuid))
|
27
|
-
val ? Resque::Status.new(uuid, decode(val)) : nil
|
28
|
-
end
|
29
|
-
|
30
|
-
# set a status by UUID. <tt>messages</tt> can be any number of stirngs or hashes
|
31
|
-
# that are merged in order to create a single status.
|
32
|
-
def self.set(uuid, *messages)
|
33
|
-
val = Resque::Status.new(uuid, *messages)
|
34
|
-
redis.set(status_key(uuid), encode(val))
|
35
|
-
if expire_in
|
36
|
-
redis.expire(status_key(uuid), expire_in)
|
37
|
-
end
|
38
|
-
val
|
39
|
-
end
|
40
|
-
|
41
|
-
# clear statuses from redis passing an optional range. See `statuses` for info
|
42
|
-
# about ranges
|
43
|
-
def self.clear(range_start = nil, range_end = nil)
|
44
|
-
status_ids(range_start, range_end).each do |id|
|
45
|
-
redis.del(status_key(id))
|
46
|
-
redis.zrem(set_key, id)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# returns a Redisk::Logger scoped to the UUID. Any options passed are passed
|
51
|
-
# to the logger initialization.
|
52
|
-
#
|
53
|
-
# Ensures that Redisk is logging to the same Redis connection as Resque.
|
54
|
-
def self.logger(uuid, options = {})
|
55
|
-
Redisk.redis = redis
|
56
|
-
Redisk::Logger.new(logger_key(uuid), options)
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.count
|
60
|
-
redis.zcard(set_key)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Return <tt>num</tt> Resque::Status objects in reverse chronological order.
|
64
|
-
# By default returns the entire set.
|
65
|
-
# @param [Numeric] range_start The optional starting range
|
66
|
-
# @param [Numeric] range_end The optional ending range
|
67
|
-
# @example retuning the last 20 statuses
|
68
|
-
# Resque::Status.statuses(0, 20)
|
69
|
-
def self.statuses(range_start = nil, range_end = nil)
|
70
|
-
status_ids(range_start, range_end).collect do |id|
|
71
|
-
get(id)
|
72
|
-
end.compact
|
73
|
-
end
|
74
|
-
|
75
|
-
# Return the <tt>num</tt> most recent status/job UUIDs in reverse chronological order.
|
76
|
-
def self.status_ids(range_start = nil, range_end = nil)
|
77
|
-
unless range_end && range_start
|
78
|
-
# Because we want a reverse chronological order, we need to get a range starting
|
79
|
-
# by the higest negative number.
|
80
|
-
redis.zrevrange(set_key, 0, -1) || []
|
81
|
-
else
|
82
|
-
# Because we want a reverse chronological order, we need to get a range starting
|
83
|
-
# by the higest negative number. The ordering is transparent from the API user's
|
84
|
-
# perspective so we need to convert the passed params
|
85
|
-
(redis.zrevrange(set_key, (range_start.abs), ((range_end || 1).abs)) || [])
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Kill the job at UUID on its next iteration this works by adding the UUID to a
|
90
|
-
# kill list (a.k.a. a list of jobs to be killed. Each iteration the job checks
|
91
|
-
# if it _should_ be killed by calling <tt>tick</tt> or <tt>at</tt>. If so, it raises
|
92
|
-
# a <tt>Resque::JobWithStatus::Killed</tt> error and sets the status to 'killed'.
|
93
|
-
def self.kill(uuid)
|
94
|
-
redis.sadd(kill_key, uuid)
|
95
|
-
end
|
96
|
-
|
97
|
-
# Remove the job at UUID from the kill list
|
98
|
-
def self.killed(uuid)
|
99
|
-
redis.srem(kill_key, uuid)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Return the UUIDs of the jobs on the kill list
|
103
|
-
def self.kill_ids
|
104
|
-
redis.smembers(kill_key)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Check whether a job with UUID is on the kill list
|
108
|
-
def self.should_kill?(uuid)
|
109
|
-
redis.sismember(kill_key, uuid)
|
110
|
-
end
|
111
|
-
|
112
|
-
# The time in seconds that jobs and statuses should expire from Redis (after
|
113
|
-
# the last time they are touched/updated)
|
114
|
-
def self.expire_in
|
115
|
-
@expire_in
|
116
|
-
end
|
117
|
-
|
118
|
-
# Set the <tt>expire_in</tt> time in seconds
|
119
|
-
def self.expire_in=(seconds)
|
120
|
-
@expire_in = seconds.nil? ? nil : seconds.to_i
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.status_key(uuid)
|
124
|
-
"status:#{uuid}"
|
125
|
-
end
|
126
|
-
|
127
|
-
def self.set_key
|
128
|
-
"_statuses"
|
129
|
-
end
|
130
|
-
|
131
|
-
def self.kill_key
|
132
|
-
"_kill"
|
133
|
-
end
|
134
|
-
|
135
|
-
def self.logger_key(uuid)
|
136
|
-
"_log:#{uuid}"
|
137
|
-
end
|
138
|
-
|
139
|
-
def self.generate_uuid
|
140
|
-
UUID.generate(:compact)
|
141
|
-
end
|
142
|
-
|
143
|
-
def self.hash_accessor(name, options = {})
|
144
|
-
options[:default] ||= nil
|
145
|
-
coerce = options[:coerce] ? ".#{options[:coerce]}" : ""
|
146
|
-
module_eval <<-EOT
|
147
|
-
def #{name}
|
148
|
-
value = (self['#{name}'] ? self['#{name}']#{coerce} : #{options[:default].inspect})
|
149
|
-
yield value if block_given?
|
150
|
-
value
|
151
|
-
end
|
152
|
-
|
153
|
-
def #{name}=(value)
|
154
|
-
self['#{name}'] = value
|
155
|
-
end
|
156
|
-
|
157
|
-
def #{name}?
|
158
|
-
!!self['#{name}']
|
159
|
-
end
|
160
|
-
EOT
|
161
|
-
end
|
162
|
-
|
163
|
-
STATUSES = %w{queued working completed failed killed}.freeze
|
164
|
-
|
165
|
-
hash_accessor :uuid
|
166
|
-
hash_accessor :name
|
167
|
-
hash_accessor :status
|
168
|
-
hash_accessor :message
|
169
|
-
hash_accessor :time
|
170
|
-
hash_accessor :options
|
171
|
-
|
172
|
-
hash_accessor :num
|
173
|
-
hash_accessor :total
|
174
|
-
|
175
|
-
# Create a new Resque::Status object. If multiple arguments are passed
|
176
|
-
# it is assumed the first argument is the UUID and the rest are status objects.
|
177
|
-
# All arguments are subsequentily merged in order. Strings are assumed to
|
178
|
-
# be messages.
|
179
|
-
def initialize(*args)
|
180
|
-
super nil
|
181
|
-
base_status = {
|
182
|
-
'time' => Time.now.to_i,
|
183
|
-
'status' => 'queued'
|
184
|
-
}
|
185
|
-
base_status['uuid'] = args.shift if args.length > 1
|
186
|
-
status_hash = args.inject(base_status) do |final, m|
|
187
|
-
m = {'message' => m} if m.is_a?(String)
|
188
|
-
final.merge(m || {})
|
189
|
-
end
|
190
|
-
self.replace(status_hash)
|
191
|
-
end
|
192
|
-
|
193
|
-
# calculate the % completion of the job based on <tt>status</tt>, <tt>num</tt>
|
194
|
-
# and <tt>total</tt>
|
195
|
-
def pct_complete
|
196
|
-
case status
|
197
|
-
when 'completed' then 100
|
198
|
-
when 'queued' then 0
|
199
|
-
else
|
200
|
-
t = (total == 0 || total.nil?) ? 1 : total
|
201
|
-
(((num || 0).to_f / t.to_f) * 100).to_i
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# Return the time of the status initialization. If set returns a <tt>Time</tt>
|
206
|
-
# object, otherwise returns nil
|
207
|
-
def time
|
208
|
-
time? ? Time.at(self['time']) : nil
|
209
|
-
end
|
210
|
-
|
211
|
-
STATUSES.each do |status|
|
212
|
-
define_method("#{status}?") do
|
213
|
-
self['status'] === status
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
# Can the job be killed? 'failed', 'completed', and 'killed' jobs cant be killed
|
218
|
-
# (for pretty obvious reasons)
|
219
|
-
def killable?
|
220
|
-
!['failed', 'completed', 'killed'].include?(self.status)
|
221
|
-
end
|
222
|
-
|
223
|
-
unless method_defined?(:to_json)
|
224
|
-
def to_json(*args)
|
225
|
-
json
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
# Return a JSON representation of the current object.
|
230
|
-
def json
|
231
|
-
h = self.dup
|
232
|
-
h['pct_complete'] = pct_complete
|
233
|
-
self.class.encode(h)
|
234
|
-
end
|
235
|
-
|
236
|
-
def inspect
|
237
|
-
"#<Resque::Status #{super}>"
|
238
|
-
end
|
239
|
-
|
240
|
-
end
|
241
|
-
end
|
5
|
+
require 'resque/plugins/status'
|
6
|
+
require 'resque/job_with_status'
|
data/lib/resque/status_server.rb
CHANGED
@@ -1,53 +1,58 @@
|
|
1
|
-
require 'resque
|
1
|
+
require 'resque-status'
|
2
2
|
|
3
3
|
module Resque
|
4
4
|
module StatusServer
|
5
|
-
|
5
|
+
|
6
6
|
VIEW_PATH = File.join(File.dirname(__FILE__), 'server', 'views')
|
7
|
-
|
7
|
+
|
8
8
|
def self.registered(app)
|
9
|
-
|
9
|
+
|
10
10
|
app.get '/statuses' do
|
11
11
|
@start = params[:start].to_i
|
12
12
|
@end = @start + (params[:per_page] || 50)
|
13
|
-
@statuses = Resque::Status.statuses(@start, @end)
|
13
|
+
@statuses = Resque::Plugins::Status::Hash.statuses(@start, @end)
|
14
14
|
@size = @statuses.size
|
15
15
|
status_view(:statuses)
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
app.get '/statuses/:id.js' do
|
19
|
-
@status = Resque::Status.get(params[:id])
|
19
|
+
@status = Resque::Plugins::Status::Hash.get(params[:id])
|
20
20
|
content_type :js
|
21
21
|
@status.json
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
app.get '/statuses/:id' do
|
25
|
-
@status = Resque::Status.get(params[:id])
|
25
|
+
@status = Resque::Plugins::Status::Hash.get(params[:id])
|
26
26
|
status_view(:status)
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
app.post '/statuses/:id/kill' do
|
30
|
-
Resque::Status.kill(params[:id])
|
30
|
+
Resque::Plugins::Status::Hash.kill(params[:id])
|
31
31
|
redirect u(:statuses)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
app.post '/statuses/clear' do
|
35
|
-
Resque::Status.clear
|
35
|
+
Resque::Plugins::Status::Hash.clear
|
36
36
|
redirect u(:statuses)
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
|
+
app.post '/statuses/clear/completed' do
|
40
|
+
Resque::Status.clear_completed
|
41
|
+
redirect u(:statuses)
|
42
|
+
end
|
43
|
+
|
39
44
|
app.get "/statuses.poll" do
|
40
45
|
content_type "text/plain"
|
41
46
|
@polling = true
|
42
47
|
|
43
48
|
@start = params[:start].to_i
|
44
49
|
@end = @start + (params[:per_page] || 50)
|
45
|
-
@statuses = Resque::Status.statuses(@start, @end)
|
50
|
+
@statuses = Resque::Plugins::Status::Hash.statuses(@start, @end)
|
46
51
|
@size = @statuses.size
|
47
52
|
|
48
53
|
status_view(:statuses, {:layout => false})
|
49
54
|
end
|
50
|
-
|
55
|
+
|
51
56
|
app.helpers do
|
52
57
|
def status_view(filename, options = {}, locals = {})
|
53
58
|
erb(File.read(File.join(::Resque::StatusServer::VIEW_PATH, "#{filename}.erb")), options, locals)
|
@@ -62,9 +67,9 @@ module Resque
|
|
62
67
|
"<p class='poll'>#{text}</p>"
|
63
68
|
end
|
64
69
|
end
|
65
|
-
|
70
|
+
|
66
71
|
app.tabs << "Statuses"
|
67
|
-
|
72
|
+
|
68
73
|
end
|
69
74
|
|
70
75
|
end
|
data/resque-status.gemspec
CHANGED
@@ -4,26 +4,31 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.
|
7
|
+
s.name = "resque-status"
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aaron Quint"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2012-01-22"
|
13
|
+
s.description = "resque-status is an extension to the resque queue system that provides simple trackable jobs. It provides a Resque::Plugins::Status::Hash class which can set/get the statuses of jobs and a Resque::Plugins::Status class that when included provides easily trackable/killable jobs."
|
14
|
+
s.email = "aaron@quirkey.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
17
|
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
21
23
|
"LICENSE",
|
22
24
|
"README.rdoc",
|
23
25
|
"Rakefile",
|
24
26
|
"examples/sleep_job.rb",
|
25
27
|
"init.rb",
|
28
|
+
"lib/resque-status.rb",
|
26
29
|
"lib/resque/job_with_status.rb",
|
30
|
+
"lib/resque/plugins/status.rb",
|
31
|
+
"lib/resque/plugins/status/hash.rb",
|
27
32
|
"lib/resque/server/views/status.erb",
|
28
33
|
"lib/resque/server/views/status_styles.erb",
|
29
34
|
"lib/resque/server/views/statuses.erb",
|
@@ -32,25 +37,37 @@ Gem::Specification.new do |s|
|
|
32
37
|
"resque-status.gemspec",
|
33
38
|
"test/redis-test.conf",
|
34
39
|
"test/test_helper.rb",
|
35
|
-
"test/
|
36
|
-
"test/
|
40
|
+
"test/test_resque_plugins_status.rb",
|
41
|
+
"test/test_resque_plugins_status_hash.rb"
|
37
42
|
]
|
38
|
-
s.homepage =
|
43
|
+
s.homepage = "http://github.com/quirkey/resque-status"
|
39
44
|
s.require_paths = ["lib"]
|
40
|
-
s.rubyforge_project =
|
41
|
-
s.rubygems_version =
|
42
|
-
s.summary =
|
45
|
+
s.rubyforge_project = "quirkey"
|
46
|
+
s.rubygems_version = "1.8.10"
|
47
|
+
s.summary = "resque-status is an extension to the resque queue system that provides simple trackable jobs."
|
43
48
|
|
44
49
|
if s.respond_to? :specification_version then
|
45
50
|
s.specification_version = 3
|
46
51
|
|
47
52
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_runtime_dependency(%q<redisk>, [">= 0.2.1"])
|
54
|
+
s.add_runtime_dependency(%q<resque>, [">= 1.3.1"])
|
55
|
+
s.add_runtime_dependency(%q<uuid>, [">= 2.0.2"])
|
56
|
+
s.add_runtime_dependency(%q<mocha>, [">= 0.9.8"])
|
57
|
+
s.add_runtime_dependency(%q<shoulda>, [">= 2.10.2"])
|
58
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
48
59
|
s.add_runtime_dependency(%q<uuid>, [">= 2.0.2"])
|
49
60
|
s.add_runtime_dependency(%q<resque>, [">= 1.3.1"])
|
50
61
|
s.add_runtime_dependency(%q<redisk>, [">= 0.2.1"])
|
51
62
|
s.add_development_dependency(%q<shoulda>, [">= 2.10.2"])
|
52
63
|
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
53
64
|
else
|
65
|
+
s.add_dependency(%q<redisk>, [">= 0.2.1"])
|
66
|
+
s.add_dependency(%q<resque>, [">= 1.3.1"])
|
67
|
+
s.add_dependency(%q<uuid>, [">= 2.0.2"])
|
68
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
69
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.2"])
|
70
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
54
71
|
s.add_dependency(%q<uuid>, [">= 2.0.2"])
|
55
72
|
s.add_dependency(%q<resque>, [">= 1.3.1"])
|
56
73
|
s.add_dependency(%q<redisk>, [">= 0.2.1"])
|
@@ -58,6 +75,12 @@ Gem::Specification.new do |s|
|
|
58
75
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
59
76
|
end
|
60
77
|
else
|
78
|
+
s.add_dependency(%q<redisk>, [">= 0.2.1"])
|
79
|
+
s.add_dependency(%q<resque>, [">= 1.3.1"])
|
80
|
+
s.add_dependency(%q<uuid>, [">= 2.0.2"])
|
81
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
82
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.2"])
|
83
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
61
84
|
s.add_dependency(%q<uuid>, [">= 2.0.2"])
|
62
85
|
s.add_dependency(%q<resque>, [">= 1.3.1"])
|
63
86
|
s.add_dependency(%q<redisk>, [">= 0.2.1"])
|