Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding plugin

  • Loading branch information...
commit 69045d2453bca0a1c1582ba4b93359d5baa2f4da 1 parent cc308b1
@eac authored
View
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Eric Chapweske
+
+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:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
23 Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the delayed job admin plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the delayed job admin plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'Fixie'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
35 app/controllers/delayed_jobs_controller.rb
@@ -0,0 +1,35 @@
+class DelayedJobsController < DelayedJobAdmin::Config.parent_controller_class
+ unloadable
+
+ def index
+ @statistics = current_model.statistics
+ @jobs = current_model.all
+
+ respond_to do |format|
+ format.html
+ format.json { render :json => @jobs }
+ end
+ end
+
+ def destroy
+ @job = current_job
+ @job.destroy
+ flash[:success] = "Job destroyed (##{@job.to_param})"
+
+ respond_to do |format|
+ format.html { redirect_to delayed_jobs_path }
+ format.json { head :no_content }
+ end
+ end
+
+ protected
+
+ def current_job
+ current_model.find(params[:id])
+ end
+
+ def current_model
+ Delayed::Job
+ end
+
+end
View
34 app/views/delayed_jobs/_job.html.erb
@@ -0,0 +1,34 @@
+<li id='<%= dom_id(job) %>' class="job <%= job.statuses.join(' ') %>">
+ <div class="summary">
+ <%= job.run_at.to_s(:short) %>
+ <a href="#details_link" class="details_link"><%= job.humanized_handler %></a>
+ <span class="actions">
+ <%= link_to 'delete', delayed_job_path(job), :method => :delete, :class => 'dangerous' %>
+ </span>
+ </div>
+ <div class="details">
+ <% if job.priority? %>
+ <div class="priority">
+ <span class="title">Priority</span> <%= job.priority %>
+ </div>
+ <% end %>
+ <% unless job.last_error? #if job.locked_at? %>
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943<%#= job.locked_by %>
+ <span class="title">on</span> August 11, 2009 20:13<%#= job.locked_at.to_s(:long) %>
+ </div>
+ <% end %>
+ <% if job.failed? || job.last_error? %>
+ <div class="failed">
+ <%= 2.ordinalize %> <%#= job.attempts %>
+ <span class="title">attempt failed</span> August 11, 2009 20:13 <%#= job.failed_at.to_s(:long) %>
+ <pre class="backtrace"><%= job.last_error %></pre>
+ </div>
+ <% end %>
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> <%= job.created_at.to_s(:long) %>
+ <span class="titles"><em>last updated</em></span> <%= job.updated_at.to_s(:long) %>
+ </div>
+ </div>
+</li>
+
View
42 app/views/delayed_jobs/index.html.erb
@@ -0,0 +1,42 @@
+<div id="page">
+ <div class="overview">
+ <% @statistics.each do |title, count| %>
+ <a class="<%= title %>_jobs statistic <%= 'active' if title == :total %>" href="#">
+ <span class="count"><%= count %></span>
+ <span class="title"><%= title %></span>
+ </a>
+ <% end %>
+ </div>
+ <ul class="jobs">
+ <%= render :partial => 'job', :collection => @jobs %>
+ </ul>
+</div>
+
+<% content_for(:javascript) do %>
+ <%= javascript_include_tag 'delayed_job_admin' %>
+
+ <script type="text/javascript">
+
+ $(document).ready(function() {
+
+ // Toggle
+ $('.job .details').hide();
+
+ $('.job .details_link').click(function() {
+ $(this).parents('.job').children('.details').slideToggle('fast');
+ });
+
+ // Filter
+ $('.failed_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this, '.failed');
+ })
+ $('.locked_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this, '.locked');
+ })
+ $('.total_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this);
+ })
+
+ });
+ </script>
+<% end %>
View
6 config/routes.rb
@@ -0,0 +1,6 @@
+ActionController::Routing::Routes.draw do |map|
+
+ map.resources :delayed_jobs, :controller => 'delayed_jobs'
+
+end
+
View
699 examples/index.html
@@ -0,0 +1,699 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<head>
+ <title>ChatterBox Administration</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?3.0.0b1/build/cssfonts/fonts-min.css&3.0.0b1/build/cssreset/reset-min.css&3.0.0b1/build/cssbase/base-min.css">
+ <link href="../public/stylesheets/delayed_job_admin.css" media="all" rel="stylesheet" type="text/css" />
+
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript">
+ google.load("jquery", "1.3.2");
+ </script>
+ <style type="text/css">
+ html { color: white; background-color: black; }
+ h1.logo { padding: 0.5em; }
+ #header .current { color: #00a6ff; }
+ #header h2 { display: inline; margin-right: 2em; }
+ #header { text-align: center; }
+ </style>
+</head>
+<body>
+
+ <h1 class="logo">Examples R Us Administration</h1>
+ <div id="header">
+ <h2>Dashboard</h2>
+ <h2 class="current">Delayed Jobs</h2>
+ <h2>Secret Data</h2>
+ </div>
+
+ <div id="page">
+ <div class="overview">
+
+ <a class="failed_jobs statistic " href="#">
+ <span class="count">0</span>
+ <span class="title">failed</span>
+ </a>
+
+ <a class="locked_jobs statistic " href="#">
+ <span class="count">0</span>
+ <span class="title">locked</span>
+ </a>
+
+ <a class="total_jobs statistic active" href="#">
+ <span class="count">25</span>
+ <span class="title">total</span>
+ </a>
+
+ </div>
+ <ul class="jobs">
+ <li id='delayed_job_12' class="job ">
+ <div class="summary">
+ 11 Aug 23:34
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/12" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 11, 2009 23:34
+ <span class="titles"><em>last updated</em></span> August 11, 2009 23:34
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_13' class="job ">
+ <div class="summary">
+ 11 Aug 23:34
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/13" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 11, 2009 23:34
+ <span class="titles"><em>last updated</em></span> August 11, 2009 23:34
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_14' class="job ">
+ <div class="summary">
+ 11 Aug 23:35
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/14" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 11, 2009 23:35
+ <span class="titles"><em>last updated</em></span> August 11, 2009 23:35
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_15' class="job ">
+ <div class="summary">
+ 11 Aug 23:58
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/15" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 11, 2009 23:58
+ <span class="titles"><em>last updated</em></span> August 11, 2009 23:58
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_16' class="job ">
+ <div class="summary">
+ 12 Aug 00:19
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/16" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 00:19
+ <span class="titles"><em>last updated</em></span> August 12, 2009 00:19
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_17' class="job ">
+ <div class="summary">
+ 12 Aug 00:25
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/17" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 00:25
+ <span class="titles"><em>last updated</em></span> August 12, 2009 00:25
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_18' class="job ">
+ <div class="summary">
+ 12 Aug 01:05
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/18" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 01:05
+ <span class="titles"><em>last updated</em></span> August 12, 2009 01:05
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_19' class="job ">
+ <div class="summary">
+ 12 Aug 01:06
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/19" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 01:06
+ <span class="titles"><em>last updated</em></span> August 12, 2009 01:06
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_20' class="job ">
+ <div class="summary">
+ 12 Aug 01:15
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/20" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 01:15
+ <span class="titles"><em>last updated</em></span> August 12, 2009 01:15
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_21' class="job ">
+ <div class="summary">
+ 12 Aug 01:28
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/21" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 01:28
+ <span class="titles"><em>last updated</em></span> August 12, 2009 01:28
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_22' class="job ">
+ <div class="summary">
+ 12 Aug 07:50
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/22" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 07:50
+ <span class="titles"><em>last updated</em></span> August 12, 2009 07:50
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_23' class="job ">
+ <div class="summary">
+ 12 Aug 23:08
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/23" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 12, 2009 23:08
+ <span class="titles"><em>last updated</em></span> August 12, 2009 23:08
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_24' class="job ">
+ <div class="summary">
+ 13 Aug 21:00
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/24" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 13, 2009 21:00
+ <span class="titles"><em>last updated</em></span> August 13, 2009 21:00
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_25' class="job ">
+ <div class="summary">
+ 19 Aug 21:41
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/25" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 21:41
+ <span class="titles"><em>last updated</em></span> August 19, 2009 21:41
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_26' class="job ">
+ <div class="summary">
+ 19 Aug 22:07
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/26" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 22:07
+ <span class="titles"><em>last updated</em></span> August 19, 2009 22:07
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_27' class="job ">
+ <div class="summary">
+ 19 Aug 22:09
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/27" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 22:09
+ <span class="titles"><em>last updated</em></span> August 19, 2009 22:09
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_28' class="job ">
+ <div class="summary">
+ 19 Aug 23:20
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/28" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 23:20
+ <span class="titles"><em>last updated</em></span> August 19, 2009 23:20
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_29' class="job ">
+ <div class="summary">
+ 19 Aug 23:26
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/29" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 23:26
+ <span class="titles"><em>last updated</em></span> August 19, 2009 23:26
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_30' class="job ">
+ <div class="summary">
+ 19 Aug 23:26
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/30" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 23:26
+ <span class="titles"><em>last updated</em></span> August 19, 2009 23:26
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_31' class="job ">
+ <div class="summary">
+ 19 Aug 23:31
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/31" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 19, 2009 23:31
+ <span class="titles"><em>last updated</em></span> August 19, 2009 23:31
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_32' class="job ">
+ <div class="summary">
+ 20 Aug 01:50
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/32" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 20, 2009 01:50
+ <span class="titles"><em>last updated</em></span> August 20, 2009 01:50
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_33' class="job ">
+ <div class="summary">
+ 24 Aug 19:05
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/33" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 24, 2009 19:05
+ <span class="titles"><em>last updated</em></span> August 24, 2009 19:05
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_34' class="job ">
+ <div class="summary">
+ 25 Aug 02:59
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/34" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 25, 2009 02:59
+ <span class="titles"><em>last updated</em></span> August 25, 2009 02:59
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_10' class="job ">
+ <div class="summary">
+ 25 Aug 23:35
+ <a href="#details_link" class="details_link">TwitterStatusUpdateJob
+chatter_id: 203
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/10" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="priority">
+ <span class="title">Priority</span> 10
+ </div>
+
+
+
+ <div class="failed">
+ 2nd
+ <span class="title">attempt failed</span> August 11, 2009 20:13
+ <pre class="backtrace">Couldn't find Fan with ID=1234
+/Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1591:in `find_one'
+/Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1574:in `find_from_ids'
+/Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:616:in `find'
+(irb):7:in `irb_binding'
+/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'
+/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/workspace.rb:52</pre>
+ </div>
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 11, 2009 23:03
+ <span class="titles"><em>last updated</em></span> August 25, 2009 23:37
+ </div>
+ </div>
+</li>
+ <li id='delayed_job_35' class="job ">
+ <div class="summary">
+ 26 Aug 21:41
+ <a href="#details_link" class="details_link">DownloadTwitterFriendsJob
+fan_id: 187
+</a>
+ <span class="actions">
+ <a href="/delayed_jobs/35" class="dangerous" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', '4ZJ0kSVF//xTAZrMhsuSnZp6fS1MRcO1jds/QkcDsP0='); f.appendChild(s);f.submit();return false;">delete</a>
+ </span>
+ </div>
+ <div class="details">
+
+ <div class="locked">
+ <span class="title">Locked by</span> Pid 23343-2943
+ <span class="title">on</span> August 11, 2009 20:13
+ </div>
+
+
+ <div class="timestamps">
+ <span class="titles"><em>Created</em></span> August 26, 2009 21:41
+ <span class="titles"><em>last updated</em></span> August 26, 2009 21:41
+ </div>
+ </div>
+</li>
+
+ </ul>
+</div>
+
+ <script src="../public/javascripts/delayed_job_admin.js" type="text/javascript"></script>
+
+ <script type="text/javascript">
+
+ $(document).ready(function() {
+
+ // Toggle
+ $('.job .details').hide();
+
+ $('.job .details_link').click(function() {
+ $(this).parents('.job').children('.details').slideToggle('fast');
+ });
+
+ // Filter
+ $('.failed_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this, '.failed');
+ })
+ $('.locked_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this, '.locked');
+ })
+ $('.total_jobs').click(function() {
+ DelayedJob.UI.filterJobs(this);
+ })
+
+ });
+ </script>
+
+
+
+
+
+
+</body>
+</html>
View
2  init.rb
@@ -0,0 +1,2 @@
+require 'delayed_job_admin'
+#File.join(File.dirname(__FILE__), 'lib',
View
2  lib/delayed_job_admin.rb
@@ -0,0 +1,2 @@
+require File.join(File.dirname(__FILE__), 'delayed_job_admin', 'administration')
+Delayed::Job.__send__(:include, DelayedJobAdmin::Administration)
View
40 lib/delayed_job_admin/administration.rb
@@ -0,0 +1,40 @@
+module DelayedJobAdmin
+ module Administration
+ HANDLER_IGNORE_PATTERN = /--- !ruby\/object:/
+
+ def self.included(base)
+ base.__send__(:extend, Statistics)
+ end
+
+ def humanized_handler
+ handler.sub(HANDLER_IGNORE_PATTERN, '')
+ end
+
+ def statuses
+ statuses = []
+ statuses << :failed if failed?
+ statuses << :locked if locked_at?
+ statuses
+ end
+
+ module Statistics
+ def self.extended(base)
+ base.instance_eval do
+
+ named_scope :failed, :conditions => 'failed_at is not null'
+ named_scope :locked, :conditions => 'locked_at is not null'
+
+ end
+ end
+
+ def statistics
+ stats = ActiveSupport::OrderedHash.new
+ stats[:failed] = failed.count
+ stats[:locked] = locked.count
+ stats[:total] = count
+ stats
+ end
+ end
+
+ end
+end
View
14 lib/delayed_job_admin/config.rb
@@ -0,0 +1,14 @@
+module DelayedJobAdmin
+ module Config
+
+ # Specify the controller DelayedAdmin controllers inherit from
+ # Redefine in app/lib/delayed_admin/config.rb:
+ # module DelayedAdmin::Config
+ # def self.parent_controller_class() AdminController end
+ # end
+ def self.parent_controller_class
+ ActionController::Base
+ end
+
+ end
+end
View
32 public/javascripts/delayed_job_admin.js
@@ -0,0 +1,32 @@
+DelayedJob = {};
+DelayedJob.UI = {
+
+ tabTo: function(element) {
+ element.siblings('.active').removeClass('active');
+ element.addClass('active');
+ },
+
+ filterJobs: function(tab, selector) {
+ this.tabTo($(tab));
+ this.bounce('.jobs', function() {
+ DelayedJob.UI.filter('.job', selector);
+ });
+ },
+
+ bounce: function(selector, callback) {
+ var element = $(selector);
+ element.slideUp(function() {
+ callback();
+ element.slideDown('slow');
+ });
+ },
+
+ filter: function(selector, filter_selector) {
+ if (filter_selector) {
+ $(selector).hide();
+ selector += filter_selector;
+ }
+ $(selector).show();
+ }
+
+};
View
107 public/stylesheets/delayed_job_admin.css
@@ -0,0 +1,107 @@
+/* Global */
+
+#page {
+ color: black;
+ background-color: #00a6ff;
+ font-size: 1.25em;
+ padding: 5em;
+}
+
+#page a {
+ outline: none;
+}
+
+#page pre { background-color: #e6f6ff; }
+
+#page a.dangerous {
+ color: #ff8b00;
+ text-decoration: none;
+}
+
+#page a.dangerous:hover {
+ color: white;
+ background-color: #ff8b00;
+}
+
+.backtrace {
+ margin-left: 1.5em;
+ overflow: auto;
+}
+
+ .backtrace:first-line { font-weight: bold; }
+
+/* Overview */
+.overview { margin-left: 4em; }
+
+ .overview a { margin-right: 0.5em; }
+
+ .overview .total_jobs { color: white; }
+ .overview .locked_jobs { color: yellow; }
+ .overview .failed_jobs { color: #ff8b00; }
+
+ .statistic {
+ display: inline;
+ font-size: 2em;
+ text-align: center;
+ }
+
+ .statistic .count { font-weight: bold; }
+ .statistic .title { color: black; }
+
+ a.statistic {
+ border-top: 0.15em solid #00a6ff;
+ border-bottom: none;
+ font-weight: bold;
+ opacity: 0.85;
+ padding: 0.5em;
+ }
+
+ a.statistic:hover,
+ a.statistic.active {
+ border-color: #80d2ff;
+ opacity: 1;
+ }
+
+/* Jobs */
+
+.jobs {
+ background-color: #80d2ff;
+ max-width: 70em;
+ padding: 1em;
+ -webkit-border-radius: 1em;
+ -moz-border-radius: 1em;
+}
+
+.job {
+ background-color: white;
+ border-left: 0.15em solid white;
+ list-style-type: none;
+ margin: 0.5em;
+ padding: 1em;
+ -webkit-box-shadow: 0.25em 0.25em 0.5em rgba(0,0,0,0.6);
+ -moz-box-shadow: 0.25em 0.25em 0.5em rgba(0,0,0,0.6);
+}
+
+ .job .details_link { font-size: 1.25em; }
+
+ .job a {
+ color: #80d2ff;
+ margin-left: 3em;
+ padding: 1em;
+ }
+
+ .job a:hover,
+ .job a:focus,
+ .job a:active { color: #00a6ff; }
+
+ .job.locked,
+ .job.failed.locked { border-color: yellow; }
+ .job.failed { border-color: #ff8b00; }
+
+ .job .details {
+ background-color: white;
+ color: black;
+ margin: 1em 0 0 1.5em;
+ }
+
+ .details .title { font-weight: bold; }
View
18 tasks/delayed_job_admin_tasks.rake
@@ -0,0 +1,18 @@
+namespace :delayed_job_admin do
+ desc "Copy public files to main application."
+ task :copy_assets do
+ plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ stylesheet_path = 'public/stylesheets/delayed_job_admin.css'
+ javascript_path = 'public/javascripts/delayed_job_admin.js'
+ assets = {
+ File.join(plugin_root, stylesheet_path) => File.join(Rails.root, stylesheet_path),
+ File.join(plugin_root, javascript_path) => File.join(Rails.root, javascript_path)
+ }
+
+ assets.each do |asset_plugin_path, asset_public_path|
+ puts "Copying #{asset_plugin_path} to #{asset_public_path}"
+ FileUtils.copy_entry(asset_plugin_path, asset_public_path, false, false, true)
+ end
+
+ end
+end
View
56 test/functional/delayed_jobs_controller_test.rb
@@ -0,0 +1,56 @@
+require 'test_helper'
+class DelayedJobsControllerTest < ActionController::TestCase
+
+ context "getting the index" do
+ setup do
+ @job = Object.send_later(:inspect)
+ end
+
+ should "succeed" do
+ get :index
+ assert_response :success
+ end
+ end
+
+ context "destroying a job" do
+
+ setup do
+ @job = Object.send_later(:inspect)
+ end
+
+ context "with HTML format" do
+ should "redirect to admin_jobs_path" do
+ delete :destroy, :id => @job.to_param
+ assert_redirected_to delayed_jobs_path
+ end
+
+ should "flash a success message" do
+ delete :destroy, :id => @job.to_param
+ assert_match /Job destroyed/, flash[:success]
+ end
+
+ should "destroy the job" do
+ delete :destroy, :id => @job.to_param
+ assert_raise ActiveRecord::RecordNotFound do
+ @job.reload
+ end
+ end
+ end
+
+ context "with JSON format" do
+ should "respond with 204 No Content" do
+ delete :destroy, :id => @job.to_param, :format => 'json'
+ assert_response :no_content
+ end
+
+ should "destroy the job" do
+ delete :destroy, :id => @job.to_param, :format => 'json'
+ assert_raise ActiveRecord::RecordNotFound do
+ @job.reload
+ end
+ end
+ end
+
+ end
+
+end
View
10 test/test_helper.rb
@@ -0,0 +1,10 @@
+ENV["RAILS_ENV"] = "test"
+
+# Load Rails
+back_steps = [ '..' ] * %w( test delayed_job_admin plugins vendor ).size
+require File.expand_path(File.join(File.dirname(__FILE__), back_steps, 'config', 'environment'))
+
+require 'test_help'
+
+gem 'thoughtbot-shoulda'
+require 'shoulda'
View
110 test/unit/administration_test.rb
@@ -0,0 +1,110 @@
+require 'test_helper'
+
+class JobAdministrationTest < ActiveSupport::TestCase
+
+ context "Administration" do
+ setup do
+ @job = Delayed::Job.new
+ end
+
+ context "statuses" do
+
+ should "include :failed and :locked when failed and locked" do
+ @job.failed_at = DateTime.now
+ @job.locked_at = DateTime.now
+
+ assert_equal [ :failed, :locked ], @job.statuses
+ end
+
+ should "not include locked when not locked" do
+ @job.failed_at = DateTime.now
+
+ assert_equal [ :failed ], @job.statuses
+ end
+
+ should "not include failed when not failed" do
+ @job.locked_at = DateTime.now
+
+ assert_equal [ :locked ], @job.statuses
+ end
+
+ should "return an empty array when neither failed nor locked" do
+ assert_equal [], @job.statuses
+ end
+
+ end
+
+ context "humanized handler" do
+
+ should "provide the handler without its ruby object identifier" do
+ @job.handler = '--- !ruby/object:TestJob {}'
+ assert_equal 'TestJob {}', @job.humanized_handler
+ end
+
+ end
+
+ context "model statistics" do
+ setup do
+ failed_job = create_delayed_job(:failed_at => Time.now)
+ locked_job = create_delayed_job(:locked_at => Time.now)
+ locked_and_failed_job = create_delayed_job(:locked_at => Time.now, :failed_at => Time.now)
+ not_locked_or_failed_job = create_delayed_job
+
+ @failed_jobs = [ failed_job, locked_and_failed_job ]
+ @locked_jobs = [ locked_job, locked_and_failed_job ]
+ end
+
+ context "named scopes" do
+
+ should "only include failed jobs in :failed scope" do
+ assert_equal @failed_jobs, Delayed::Job.failed
+ end
+
+ should "only include locked jobs in :locked scope" do
+ assert_equal @locked_jobs, Delayed::Job.locked
+ end
+
+ end
+
+ context "statistics" do
+ setup do
+ @stats = Delayed::Job.statistics
+ end
+
+ should "correctly count :failed jobs" do
+ assert_equal @failed_jobs.size, @stats[:failed]
+ end
+
+ should "correctly count of :total jobs" do
+ assert_equal Delayed::Job.count, @stats[:total]
+ end
+
+ should "correctly count of :locked jobs" do
+ assert_equal @locked_jobs.size, @stats[:locked]
+ end
+
+ should "be ordered :failed, :locked, then :total" do
+ assert_equal [ :failed, :locked, :total ], @stats.keys
+ end
+
+ end
+ end
+
+ end
+
+ protected
+
+ # Test Job via delayed_job's job_spec.rb
+ class ErrorJob
+ cattr_accessor :runs; self.runs = 0
+ def perform; raise 'did not work'; end
+ end
+
+ def create_delayed_job(attributes = {})
+ job = Delayed::Job.enqueue ErrorJob.new
+ job.__send__(:attributes=, attributes, guard_from_mass_assignment = false)
+ job.save!
+ job
+ end
+
+end

0 comments on commit 69045d2

Please sign in to comment.
Something went wrong with that request. Please try again.