- Have a working How to Install Ruby on Rails
- Get BackgroundRB
- Get Get ActiveScaffold
- Make a model:
db/migrate/create_documents.rb
class CreateDocuments < ActiveRecord::Migration
def self.up
create_table :documents do |t|
t.column :title, :string
t.column :created_at, :datetime
t.column :updated_at, :datetime
t.column :imported, :boolean
t.column :job_key, :string
t.column :progress, :integer
end
end
def self.down
drop_table :documents
end
end
- Turn on ActiveScaffold for the Document page and make an "import" button in Active Scaffold:
app/controllers/documents_controller.rb
class DocumentsController < ApplicationController
active_scaffold :document do |config|
config.action_links.add 'import', :label => 'Import',
:type => :record,
:method => 'put'
end
end
- Make a controller that will call the worker:
app/controllers/documents_controller.rb
def import
if request.xhr?
@document = Document.find(params[:id])
unless (@document.imported == true)
if ((@document.job_key == nil || ""))
job_key = "#{Time.now.to_i}-DOC#{@document.id}"
MiddleMan.new_worker(:class => :book_import_worker,
:args => {:document_id => @document.id,
:job_key => job_key},
:job_key => job_key)
@document_id = @document.id
end
end
end
end
- Make the worker you are going to call:
lib/workers/book_import_worker.rb
class BookImportWorker < BackgrounDRb::Rails
def do_work(args)
@document = Document.find_by_id(args[:document_id])
@document.job_key = args[:job_key]
@document.imported = false
@document.save!
@logger.info("Book import started on Document Job Key #{args[:job_key]}")
@progress = 1
@total = 200
while @document.progress < @total
progress(1)
sleep 2
end
@document.job_key = nil
@document.imported = true
@document.progress = 100
@document.save!
kill()
end
private
def progress(p)
@progress += p
@result = (@progress.to_f / @total) * 100
@result = 1 if @result < 1
@result = 100 if @result > 100
@logger.info("Worker job_key: #{@document.job_key},
total is: #{@total}, Progress is: #{@progress},
Percentage done is #{@result}")
@document.progress = @result.to_i
@document.save!
end
end
- Make the importing page:
app/views/documents/import.rhtml
For some reason the editor is parsing my escaped HTML as real HTML!
So I have bundled it all up here.
- Make the get status "ping" method in the controller:
app/controllers/documents_controller.rb
def ping
@document = Document.find(params[:id])
@percent = @document.progress
@document_id = @document.id
redirect_to :action => :index unless request.xhr?
end
- Make the ping.rjs file
app/views/documents/ping.rjs
page.replace_html("progressbar#{@document_id}",
:partial => "percent",
:object => @percent)
if @percent >= 100
page.replace_html("progressbar#{@document_id}",
:partial => "finished",
:object => @percent)
page.insert_html(:after, "documents-active-scaffold",
:partial => "finished_hidden")
end
- Make the progress bar partial:
app/views/documents/_percent.rhtml
It is all in here.
- Make the finished bar partial:
app/views/documents/_finished.rhtml
Same file here.
- Make the hidden finished bar
app/views/documents/_finished_hidden.rhtml
Here it is again.
- Press PLAY!
One day I'll do a screen cast... :) for now, you'll have to take my word for it that it looks really cool.
There you go!
blogLater
Mikel
¿ 6/10/2007 - I don't see any upload fields in any of your document views
Thanks,
Zack