riparian 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.
- checksums.yaml +7 -0
- data/Gemfile +14 -0
- data/MIT-LICENSE +20 -0
- data/README +44 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/app/models/flow_task.rb +46 -0
- data/lib/app/models/flow_task_input.rb +3 -0
- data/lib/app/models/flow_task_output.rb +3 -0
- data/lib/app/models/flow_task_resource.rb +19 -0
- data/lib/generators/USAGE +10 -0
- data/lib/generators/riparian_generator.rb +55 -0
- data/lib/generators/templates/flow_tasks_controller.rb +69 -0
- data/lib/generators/templates/flow_tasks_helper.rb +17 -0
- data/lib/generators/templates/migration.rb +38 -0
- data/lib/generators/templates/views/flow_tasks/_delayed_progress.html.haml +30 -0
- data/lib/generators/templates/views/flow_tasks/index.html.haml +34 -0
- data/lib/generators/templates/views/flow_tasks/run.html.haml +4 -0
- data/lib/generators/templates/views/flow_tasks/show.html.haml +64 -0
- data/lib/riparian.rb +42 -0
- data/riparian.gemspec +86 -0
- data/test/database.yml +3 -0
- data/test/flow_task_test.rb +9 -0
- data/test/riparian_test.rb +17 -0
- data/test/schema.rb +29 -0
- data/test/test_helper.rb +20 -0
- data/uninstall.rb +1 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e55bf1f5e5ba858b961fb4e2dc465f56c097013047d564d552a6a23f59fce2b0
|
4
|
+
data.tar.gz: 1d2431d5c13efcb664dd33f3f7602e4dffe22badc33bde783ff1e1197e5d294d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9bc885fab82ffc19b841517f5d8a6ff5e578850ae88446969e5af6242f89642c69225dcd402bf8c74dff9e5543acc01f48c14aae1615d8416841f32ba27eede7
|
7
|
+
data.tar.gz: 1a555b3226d288dcb85cf4a036d8f775d793966fe8f188a6ce28cf4eb35f0bd89697fec9904ac1cdf8a086ef13f5280c67964275a932830a7271ed8cc7836fee
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Ken-ichi Ueda
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Riparian
|
2
|
+
|
3
|
+
Riparian is a partial workflow system built with Delayed Job and Paperclip. It
|
4
|
+
consists of Flow Tasks, which are tasks to be performed by Delayed Job, and
|
5
|
+
Flow Task Resources, which constitute input and output data of the tasks. Flow
|
6
|
+
Task Resources can have an attached file, or a polymorphic relationship to an
|
7
|
+
ActiveRecord resource.
|
8
|
+
|
9
|
+
To make your own tasks, subclass FlowTask and implement the run method. Tasks
|
10
|
+
will be executed whenever Delayed Job gets to them.
|
11
|
+
|
12
|
+
If you need to alter Paperclip's path and url settings, you can add a
|
13
|
+
riparian.yml file to your config folder with the following settings:
|
14
|
+
|
15
|
+
flow_task_resource_file_path: paperclip/interpolation/string
|
16
|
+
flow_task_resource_file_url: paperclip/interpolation/string
|
17
|
+
|
18
|
+
Similarly you can set the max and min file sizes in bytes for file
|
19
|
+
attachments:
|
20
|
+
|
21
|
+
flow_task_resource_file_size_greater_than: 1 # Default: 1 byte
|
22
|
+
flow_task_resource_file_size_less_than: 1024 # Default: 10 megabytes
|
23
|
+
|
24
|
+
|
25
|
+
# Example
|
26
|
+
|
27
|
+
# generate controller, helper, and migration
|
28
|
+
rails generate riparian
|
29
|
+
|
30
|
+
# subclass FlowTask
|
31
|
+
class MyTask < FlowTask
|
32
|
+
def run
|
33
|
+
open(inputs.first.file.path) do |f|
|
34
|
+
txt = f.read
|
35
|
+
txt.gsub! 'foo', 'bar'
|
36
|
+
Tempfile.open('bar') do |tf|
|
37
|
+
tf.write(txt)
|
38
|
+
outputs.create(:file => tf)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Start POSTing stuff to /flow_tasks!
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
require 'rake'
|
12
|
+
require 'rake/testtask'
|
13
|
+
require 'rdoc/task'
|
14
|
+
require 'jeweler'
|
15
|
+
|
16
|
+
Jeweler::Tasks.new do |gem|
|
17
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
|
+
gem.name = "riparian"
|
19
|
+
gem.homepage = "http://github.com/kueda/riparian"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{DelayedJob-based workflow system.}
|
22
|
+
gem.description = %Q{Basically just a handful of models to make handling workflows and asynchronous server-side tasks a little easier.}
|
23
|
+
gem.email = "kenichi.ueda@gmail.com"
|
24
|
+
gem.authors = ["Ken-ichi Ueda"]
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
desc 'Default: run unit tests.'
|
30
|
+
task :default => :test
|
31
|
+
|
32
|
+
desc 'Test the riparian plugin.'
|
33
|
+
Rake::TestTask.new(:test) do |t|
|
34
|
+
t.libs << 'lib'
|
35
|
+
t.libs << 'test'
|
36
|
+
t.pattern = 'test/**/*_test.rb'
|
37
|
+
t.verbose = true
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Generate documentation for the riparian plugin.'
|
41
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = 'Riparian'
|
44
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
45
|
+
rdoc.rdoc_files.include('README')
|
46
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
47
|
+
end
|
48
|
+
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "riparian #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "lib", "riparian")
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class FlowTask < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :user
|
4
|
+
|
5
|
+
# Input resources for the task, can be any model instance or file attachment
|
6
|
+
has_many :inputs, :class_name => "FlowTaskInput", :dependent => :destroy, :inverse_of => :flow_task
|
7
|
+
|
8
|
+
# Output resources, generated by run method below
|
9
|
+
has_many :outputs, :class_name => "FlowTaskOutput", :dependent => :destroy, :inverse_of => :flow_task
|
10
|
+
|
11
|
+
accepts_nested_attributes_for :inputs, :outputs
|
12
|
+
|
13
|
+
# validates_presence_of :inputs
|
14
|
+
serialize :options
|
15
|
+
|
16
|
+
# to be used as the friendly URL
|
17
|
+
def to_param
|
18
|
+
"#{id}-#{self.class.to_s.underscore}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def status
|
22
|
+
if error_msg.present?
|
23
|
+
"error"
|
24
|
+
elsif finished_at.present?
|
25
|
+
"done"
|
26
|
+
elsif started_at.present?
|
27
|
+
"working"
|
28
|
+
else
|
29
|
+
"start"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Runs a system command with logging, captures STDIN, STDOUT, and STDERR and returns them
|
34
|
+
def run_command(cmd)
|
35
|
+
require 'open3'
|
36
|
+
Rails.logger.info "[INFO #{Time.now}] #{self} running #{cmd}"
|
37
|
+
update_attribute(:command, cmd)
|
38
|
+
stdin, stdout, stderr = Open3.popen3(cmd)
|
39
|
+
[stdin, stdout, stderr].map do |io|
|
40
|
+
s = io.read.strip rescue nil
|
41
|
+
io.close
|
42
|
+
s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class FlowTaskResource < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :flow_task
|
4
|
+
belongs_to :resource, :polymorphic => true
|
5
|
+
|
6
|
+
has_attached_file :file,
|
7
|
+
:path => Riparian.config.flow_task_resource_file_path,
|
8
|
+
:url => Riparian.config.flow_task_resource_file_url
|
9
|
+
|
10
|
+
validates_attachment_size :file,
|
11
|
+
:greater_than => Riparian.config.flow_task_resource_file_size_greater_than,
|
12
|
+
:less_than => Riparian.config.flow_task_resource_file_size_less_than
|
13
|
+
|
14
|
+
|
15
|
+
# validates_attachment_content_type :file, :content_type => /text\/plain/
|
16
|
+
# validates_attachment_file_name :file, :matches => [/\A.*\Z/]
|
17
|
+
|
18
|
+
do_not_validate_attachment_file_type :file
|
19
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class RiparianGenerator < Rails::Generators::Base
|
5
|
+
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
class_option "skip-controller", :type => :boolean, :desc => "Don't generate a controller for managing flow tasks."
|
9
|
+
class_option "skip-views", :type => :boolean, :desc => "Don't create basic haml views for managing flow tasks."
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
13
|
+
end
|
14
|
+
|
15
|
+
# Implement the required interface for Rails::Generators::Migration.
|
16
|
+
# Cribbed from DelayedJob
|
17
|
+
def self.next_migration_number(dirname) #:nodoc:
|
18
|
+
next_migration_number = current_migration_number(dirname) + 1
|
19
|
+
if ActiveRecord::Base.timestamped_migrations
|
20
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
21
|
+
else
|
22
|
+
"%.3d" % next_migration_number
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_routes
|
27
|
+
unless options["skip-controller"]
|
28
|
+
route <<-EOT
|
29
|
+
# Riparian routes
|
30
|
+
resources :flow_tasks do
|
31
|
+
member do
|
32
|
+
get :run
|
33
|
+
end
|
34
|
+
end
|
35
|
+
EOT
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_app_files
|
40
|
+
unless options["skip-controller"]
|
41
|
+
template 'flow_tasks_controller.rb', 'app/controllers/flow_tasks_controller.rb'
|
42
|
+
unless options["skip-views"]
|
43
|
+
template 'flow_tasks_helper.rb', 'app/helpers/flow_tasks_helper.rb'
|
44
|
+
directory 'views/flow_tasks', 'app/views/flow_tasks'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_migration_file
|
50
|
+
if defined?(ActiveRecord)
|
51
|
+
migration_template 'migration.rb', 'db/migrate/create_riparian.rb'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class FlowTasksController < ApplicationController
|
2
|
+
before_filter :load_flow_task, :only => [:show, :destroy, :run]
|
3
|
+
|
4
|
+
def index
|
5
|
+
@flow_tasks = FlowTask.order("id desc").paginate(:page => params[:page])
|
6
|
+
end
|
7
|
+
|
8
|
+
def show
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
klass = params[:type].camlize.constantize rescue FlowTask
|
13
|
+
@flow_task = klass.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
class_name = params.keys.detect{|k| k =~ /flow_task/}
|
18
|
+
klass = class_name.camelize.constantize rescue FlowTask
|
19
|
+
@flow_task = klass.new(params[class_name])
|
20
|
+
@flow_task.user = current_user
|
21
|
+
if @flow_task.save
|
22
|
+
flash[:notice] = "Flow task created"
|
23
|
+
redirect_to run_flow_task_path(@flow_task)
|
24
|
+
else
|
25
|
+
render :new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
# Get the flow task id and type frmo params[:id], a composite of id and type
|
31
|
+
flow_task_id, flow_task_type = params[:id].split /-/
|
32
|
+
# Convert flow task type from string to Sidekiq job class
|
33
|
+
flow_task_job = "FlowTaskJob::#{flow_task_type.camelize}".constantize
|
34
|
+
# Set @job from params[:job]
|
35
|
+
@job = params[:job]
|
36
|
+
# If @job has content, check on the status of the flow task related to the job
|
37
|
+
if @job
|
38
|
+
@flow_task = FlowTask.find(flow_task_id.to_i)
|
39
|
+
# Check whether the Sidekiq flow task job is still alive
|
40
|
+
if Sidekiq::Status::failed? @job
|
41
|
+
@flow_task.update_attribute(:error_msg, "The flow task run into system error, please contact Admin.")
|
42
|
+
end
|
43
|
+
@status = @flow_task.status
|
44
|
+
@error_msg = @flow_task.error_msg if @status == "error"
|
45
|
+
@tries = params[:tries].to_i
|
46
|
+
# Else start the Sidekiq job for the flow task
|
47
|
+
else
|
48
|
+
@job = flow_task_job.perform_async(flow_task_id)
|
49
|
+
@status = "start"
|
50
|
+
@tries = 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy
|
55
|
+
@flow_task.destroy
|
56
|
+
flash[:notice] = "Flow task destroyed"
|
57
|
+
redirect_to flow_tasks_path
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def load_flow_task
|
63
|
+
return true if @flow_task = FlowTask.find(params[:id].to_i)
|
64
|
+
flash[:error] = "That task doesn't exist"
|
65
|
+
redirect_to flow_tasks_path
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FlowTasksHelper
|
2
|
+
|
3
|
+
def flow_task_redirect_url(flow_task)
|
4
|
+
return flow_task_url(flow_task) if flow_task.redirect_url.blank?
|
5
|
+
url = flow_task.redirect_url
|
6
|
+
if url =~ /^\// || url =~ /^http/
|
7
|
+
url += if url =~ /\?/
|
8
|
+
"&flow_task_id=#{flow_task.id}"
|
9
|
+
else
|
10
|
+
"?flow_task_id=#{flow_task.id}"
|
11
|
+
end
|
12
|
+
else
|
13
|
+
send(url, :flow_task_id => flow_task.id)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class CreateRiparian < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :flow_tasks do |t|
|
4
|
+
t.string :type
|
5
|
+
t.string :options
|
6
|
+
t.string :command
|
7
|
+
t.string :error_msg
|
8
|
+
t.datetime :started_at
|
9
|
+
t.datetime :finished_at
|
10
|
+
t.datetime :deleted_at
|
11
|
+
t.integer :user_id
|
12
|
+
t.string :redirect_url
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
add_index :flow_tasks, :user_id
|
16
|
+
|
17
|
+
create_table :flow_task_resources do |t|
|
18
|
+
t.integer :flow_task_id
|
19
|
+
t.string :resource_type
|
20
|
+
t.integer :resource_id
|
21
|
+
t.string :type
|
22
|
+
t.string :file_file_name
|
23
|
+
t.string :file_content_type
|
24
|
+
t.integer :file_file_size
|
25
|
+
t.datetime :file_updated_at
|
26
|
+
t.string :extra
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
add_index :flow_task_resources, [:flow_task_id, :type]
|
30
|
+
add_index :flow_task_resources, [:resource_type, :resource_id]
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.down
|
35
|
+
drop_table :flow_tasks
|
36
|
+
drop_table :flow_task_resources
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
:ruby
|
2
|
+
loading ||= "Generating file..."
|
3
|
+
redirect_url ||= root_url
|
4
|
+
- case @status
|
5
|
+
- when "error"
|
6
|
+
.error.status.ui-state-error.big.centered
|
7
|
+
Something went wrong generating your file:
|
8
|
+
= @error_msg
|
9
|
+
- when "start", "working"
|
10
|
+
.status.big.centered.anno
|
11
|
+
%span.loading
|
12
|
+
= loading
|
13
|
+
:javascript
|
14
|
+
var tries = #{@tries.inspect};
|
15
|
+
function progress() {
|
16
|
+
if (window.location.href.match(/tries=\d+/)) {
|
17
|
+
window.location.href = window.location.href.replace(/tries=\d+/, 'tries='+(tries+1))
|
18
|
+
} else if (window.location.href.match(/\?/)) {
|
19
|
+
window.location.href += '&tries='+(tries+1)
|
20
|
+
} else {
|
21
|
+
window.location.href += '?tries='+(tries+1)
|
22
|
+
}
|
23
|
+
}
|
24
|
+
setTimeout('progress()', 5000)
|
25
|
+
- when "done"
|
26
|
+
.success.status.big.centered
|
27
|
+
Done! Redirecting...
|
28
|
+
:javascript
|
29
|
+
window.location = #{redirect_url.inspect}
|
30
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
- cols = %w(id created_at type updated_at started_at finished_at inputs outputs)
|
2
|
+
%h1 Flow Tasks
|
3
|
+
|
4
|
+
%table
|
5
|
+
%thead
|
6
|
+
%tr
|
7
|
+
- cols.each do |col|
|
8
|
+
%th= col.humanize
|
9
|
+
%tbody
|
10
|
+
- for flow_task in @flow_tasks
|
11
|
+
%tr
|
12
|
+
%td
|
13
|
+
= link_to "##{flow_task.id}", flow_task_path(flow_task)
|
14
|
+
- for col in cols - %w(inputs outputs id)
|
15
|
+
%td
|
16
|
+
= flow_task.send(col)
|
17
|
+
%td
|
18
|
+
%ul
|
19
|
+
- for input in flow_task.inputs
|
20
|
+
%li
|
21
|
+
- if input.resource
|
22
|
+
= link_to "#{input.resource_type}: #{input.resource.to_param}", input.resource
|
23
|
+
- else
|
24
|
+
= link_to input.file_file_name, input.file.url
|
25
|
+
%td
|
26
|
+
%ul
|
27
|
+
- for output in flow_task.outputs
|
28
|
+
%li
|
29
|
+
- if output.resource
|
30
|
+
= link_to "#{output.resource_type}: #{output.resource.to_param}", input.resource
|
31
|
+
- else
|
32
|
+
= link_to output.file_file_name, output.file.url
|
33
|
+
|
34
|
+
= will_paginate @flow_tasks
|
@@ -0,0 +1,64 @@
|
|
1
|
+
%h1
|
2
|
+
= "#{@flow_task.type.to_s.underscore.humanize} #{@flow_task.id}"
|
3
|
+
|
4
|
+
%table.stacked.simple
|
5
|
+
%tr
|
6
|
+
%th Created by
|
7
|
+
%td
|
8
|
+
- if current_user.id == @flow_task.user_id
|
9
|
+
you
|
10
|
+
- else
|
11
|
+
= @flow_task.user
|
12
|
+
%tr
|
13
|
+
%th Created at
|
14
|
+
%td= @flow_task.created_at
|
15
|
+
%tr
|
16
|
+
%th Started at
|
17
|
+
%td= @flow_task.started_at
|
18
|
+
%tr
|
19
|
+
%th Finished at
|
20
|
+
%td= @flow_task.finished_at
|
21
|
+
- unless @flow_task.options.blank?
|
22
|
+
%tr
|
23
|
+
%th Options
|
24
|
+
%td
|
25
|
+
%pre
|
26
|
+
= @flow_task.options.inspect
|
27
|
+
- unless @flow_task.command.blank?
|
28
|
+
%tr
|
29
|
+
%th Command
|
30
|
+
%td= @flow_task.command
|
31
|
+
- unless @flow_task.error_msg.blank?
|
32
|
+
%tr
|
33
|
+
%th Error
|
34
|
+
%td.error.status
|
35
|
+
= @flow_task.error_msg
|
36
|
+
%tr
|
37
|
+
%th Inputs
|
38
|
+
%td
|
39
|
+
%ul
|
40
|
+
- for input in @flow_task.inputs
|
41
|
+
%li
|
42
|
+
- if input.resource
|
43
|
+
= link_to "#{input.resource_type}: #{input.resource.to_param}", input.resource
|
44
|
+
- else
|
45
|
+
= link_to input.file_file_name, input.file.url
|
46
|
+
%tr
|
47
|
+
%th Outputs
|
48
|
+
%td
|
49
|
+
%ul
|
50
|
+
- for output in @flow_task.outputs
|
51
|
+
%li
|
52
|
+
- if output.resource
|
53
|
+
= link_to "#{output.resource_type}: #{output.resource.to_param}", input.resource
|
54
|
+
- else
|
55
|
+
= link_to output.file_file_name, output.file.url
|
56
|
+
- unless @flow_task.redirect_url.blank?
|
57
|
+
%th Redirect URL
|
58
|
+
%td
|
59
|
+
= link_to flow_task_redirect_url(@flow_task), flow_task_redirect_url(@flow_task)
|
60
|
+
|
61
|
+
- if current_user && @flow_task.user_id == current_user.id
|
62
|
+
.actions.stacked
|
63
|
+
= link_to "Run again", run_flow_task_path(@flow_task), :class => "button"
|
64
|
+
= link_to "Delete", flow_task_path(@flow_task), :method => :delete, :confirm => "Are you sure you want to delete this?", :class => "delete button ui-priority-secondary"
|
data/lib/riparian.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'paperclip'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module Riparian
|
6
|
+
DEFAULT_CONFIG = {
|
7
|
+
:flow_task_resource_file_path => ":rails_root/public/system/:class/:id/:filename",
|
8
|
+
:flow_task_resource_file_url => "/system/:class/:id/:filename",
|
9
|
+
:flow_task_resource_file_size_greater_than => 1, # 1 byte
|
10
|
+
:flow_task_resource_file_size_less_than => 10485760 # 10 megabytes
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.config
|
14
|
+
@config ||= OpenStruct.new(DEFAULT_CONFIG)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.config=(new_config)
|
18
|
+
@config = new_config
|
19
|
+
end
|
20
|
+
|
21
|
+
class Railtie < Rails::Railtie
|
22
|
+
config.before_configuration do
|
23
|
+
path = ::Rails.root.join('config/riparian.yml')
|
24
|
+
if ::Rails.root.join('config/riparian.yml').exist?
|
25
|
+
Riparian.config = OpenStruct.new(
|
26
|
+
DEFAULT_CONFIG.merge(
|
27
|
+
YAML.load(open(path)).symbolize_keys
|
28
|
+
)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
initializer 'riparian.initialize' do
|
34
|
+
# Load models
|
35
|
+
%w{ models }.each do |dir|
|
36
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
37
|
+
$LOAD_PATH << path
|
38
|
+
ActiveSupport::Dependencies.autoload_paths << path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/riparian.gemspec
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{riparian}
|
8
|
+
s.version = "0.3.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Ken-ichi Ueda}]
|
12
|
+
s.date = %q{2011-08-02}
|
13
|
+
s.description = %q{Basically just a handful of models to make handling workflows and asynchronous server-side tasks a little easier.}
|
14
|
+
s.email = %q{kenichi.ueda@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"Gemfile",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"init.rb",
|
25
|
+
"install.rb",
|
26
|
+
"lib/app/models/flow_task.rb",
|
27
|
+
"lib/app/models/flow_task_input.rb",
|
28
|
+
"lib/app/models/flow_task_output.rb",
|
29
|
+
"lib/app/models/flow_task_resource.rb",
|
30
|
+
"lib/generators/USAGE",
|
31
|
+
"lib/generators/riparian_generator.rb",
|
32
|
+
"lib/generators/templates/flow_tasks_controller.rb",
|
33
|
+
"lib/generators/templates/flow_tasks_helper.rb",
|
34
|
+
"lib/generators/templates/migration.rb",
|
35
|
+
"lib/generators/templates/views/flow_tasks/_delayed_progress.html.haml",
|
36
|
+
"lib/generators/templates/views/flow_tasks/index.html.haml",
|
37
|
+
"lib/generators/templates/views/flow_tasks/run.html.haml",
|
38
|
+
"lib/generators/templates/views/flow_tasks/show.html.haml",
|
39
|
+
"lib/riparian.rb",
|
40
|
+
"riparian.gemspec",
|
41
|
+
"test/database.yml",
|
42
|
+
"test/flow_task_test.rb",
|
43
|
+
"test/riparian_test.rb",
|
44
|
+
"test/schema.rb",
|
45
|
+
"test/test_helper.rb",
|
46
|
+
"uninstall.rb"
|
47
|
+
]
|
48
|
+
s.homepage = %q{http://github.com/kueda/riparian}
|
49
|
+
s.licenses = [%q{MIT}]
|
50
|
+
s.require_paths = [%q{lib}]
|
51
|
+
s.rubygems_version = %q{1.8.6}
|
52
|
+
s.summary = %q{DelayedJob-based workflow system.}
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
s.specification_version = 3
|
56
|
+
|
57
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
58
|
+
s.add_runtime_dependency(%q<rails>, ["> 3.0.0"])
|
59
|
+
s.add_runtime_dependency(%q<activesupport>, ["> 3.0.0"])
|
60
|
+
s.add_runtime_dependency(%q<rdoc>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<delayed_job>, [">= 0"])
|
62
|
+
s.add_runtime_dependency(%q<paperclip>, [">= 0"])
|
63
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
64
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
65
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<rails>, ["> 3.0.0"])
|
68
|
+
s.add_dependency(%q<activesupport>, ["> 3.0.0"])
|
69
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
70
|
+
s.add_dependency(%q<delayed_job>, [">= 0"])
|
71
|
+
s.add_dependency(%q<paperclip>, [">= 0"])
|
72
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
73
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
74
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
75
|
+
end
|
76
|
+
else
|
77
|
+
s.add_dependency(%q<rails>, ["> 3.0.0"])
|
78
|
+
s.add_dependency(%q<activesupport>, ["> 3.0.0"])
|
79
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
80
|
+
s.add_dependency(%q<delayed_job>, [">= 0"])
|
81
|
+
s.add_dependency(%q<paperclip>, [">= 0"])
|
82
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
83
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
84
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
85
|
+
end
|
86
|
+
end
|
data/test/database.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RiparianTest < ActiveSupport::TestCase
|
4
|
+
load_schema
|
5
|
+
|
6
|
+
class FlowTask < ActiveRecord::Base
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_schema_has_loaded_correctly
|
10
|
+
assert_equal [], FlowTask.all
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_riparian_configurable
|
14
|
+
assert !Riparian.config.nil?
|
15
|
+
assert !Riparian.config.flow_task_resource_file_path.nil?
|
16
|
+
end
|
17
|
+
end
|
data/test/schema.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
create_table "flow_task_resources", :force => true do |t|
|
3
|
+
t.integer "flow_task_id"
|
4
|
+
t.string "resource_type"
|
5
|
+
t.integer "resource_id"
|
6
|
+
t.string "type"
|
7
|
+
t.datetime "created_at"
|
8
|
+
t.datetime "updated_at"
|
9
|
+
t.string "file_file_name"
|
10
|
+
t.string "file_content_type"
|
11
|
+
t.integer "file_file_size"
|
12
|
+
t.datetime "file_updated_at"
|
13
|
+
t.string "extra"
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table "flow_tasks", :force => true do |t|
|
17
|
+
t.string "type"
|
18
|
+
t.string "options"
|
19
|
+
t.string "command"
|
20
|
+
t.string "error_msg"
|
21
|
+
t.datetime "started_at"
|
22
|
+
t.datetime "finished_at"
|
23
|
+
t.datetime "deleted_at"
|
24
|
+
t.integer "user_id"
|
25
|
+
t.string "redirect_url"
|
26
|
+
t.datetime "created_at"
|
27
|
+
t.datetime "updated_at"
|
28
|
+
end
|
29
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'rails/all'
|
6
|
+
require 'active_support/dependencies'
|
7
|
+
require 'riparian'
|
8
|
+
|
9
|
+
%w{ models views }.each do |dir|
|
10
|
+
path = File.join(File.dirname(__FILE__), '../lib/app', dir)
|
11
|
+
$LOAD_PATH << path
|
12
|
+
ActiveSupport::Dependencies.autoload_paths << path
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_schema
|
16
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
17
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
18
|
+
ActiveRecord::Base.establish_connection(config['test'])
|
19
|
+
load(File.dirname(__FILE__) + "/schema.rb")
|
20
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: riparian
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken-ichi Ueda
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2011-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rdoc
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: delayed_job
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: paperclip
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.0.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.0.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: jeweler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.6.2
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.6.2
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rcov
|
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
|
+
description: Basically just a handful of models to make handling workflows and asynchronous
|
126
|
+
server-side tasks a little easier.
|
127
|
+
email: kenichi.ueda@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files:
|
131
|
+
- README
|
132
|
+
files:
|
133
|
+
- Gemfile
|
134
|
+
- MIT-LICENSE
|
135
|
+
- README
|
136
|
+
- Rakefile
|
137
|
+
- VERSION
|
138
|
+
- init.rb
|
139
|
+
- install.rb
|
140
|
+
- lib/app/models/flow_task.rb
|
141
|
+
- lib/app/models/flow_task_input.rb
|
142
|
+
- lib/app/models/flow_task_output.rb
|
143
|
+
- lib/app/models/flow_task_resource.rb
|
144
|
+
- lib/generators/USAGE
|
145
|
+
- lib/generators/riparian_generator.rb
|
146
|
+
- lib/generators/templates/flow_tasks_controller.rb
|
147
|
+
- lib/generators/templates/flow_tasks_helper.rb
|
148
|
+
- lib/generators/templates/migration.rb
|
149
|
+
- lib/generators/templates/views/flow_tasks/_delayed_progress.html.haml
|
150
|
+
- lib/generators/templates/views/flow_tasks/index.html.haml
|
151
|
+
- lib/generators/templates/views/flow_tasks/run.html.haml
|
152
|
+
- lib/generators/templates/views/flow_tasks/show.html.haml
|
153
|
+
- lib/riparian.rb
|
154
|
+
- riparian.gemspec
|
155
|
+
- test/database.yml
|
156
|
+
- test/flow_task_test.rb
|
157
|
+
- test/riparian_test.rb
|
158
|
+
- test/schema.rb
|
159
|
+
- test/test_helper.rb
|
160
|
+
- uninstall.rb
|
161
|
+
homepage: http://github.com/kueda/riparian
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.7.6
|
182
|
+
signing_key:
|
183
|
+
specification_version: 3
|
184
|
+
summary: DelayedJob-based workflow system.
|
185
|
+
test_files: []
|