dalliance 0.0.1
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/.gitignore +10 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.rdoc +39 -0
- data/Rakefile +8 -0
- data/dalliance.gemspec +30 -0
- data/lib/dalliance/progress_meter.rb +43 -0
- data/lib/dalliance/version.rb +13 -0
- data/lib/dalliance.rb +139 -0
- data/lib/generators/dalliance/progress_meter/progress_meter_generator.rb +22 -0
- data/lib/generators/dalliance/progress_meter/templates/migration.rb +21 -0
- data/lib/generators/dalliance/update/templates/migration.rb.erb +11 -0
- data/lib/generators/dalliance/update/update_generator.rb +33 -0
- data/spec/dalliance/asynchronous_spec.rb +89 -0
- data/spec/dalliance/dalliance_spec.rb +4 -0
- data/spec/dalliance/synchronous_spec.rb +58 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/active_record.rb +54 -0
- metadata +147 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2012 Annkissam
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= dalliance
|
2
|
+
|
3
|
+
Opinionated background processing for ActiveRecord w/ delayed_job & state_machine
|
4
|
+
|
5
|
+
A simple wrapper for asynchronous processing w/ error handling & a progress_meter
|
6
|
+
|
7
|
+
== Getting Started
|
8
|
+
|
9
|
+
In your Gemfile:
|
10
|
+
|
11
|
+
gem "dalliance"
|
12
|
+
|
13
|
+
In your model:
|
14
|
+
|
15
|
+
class Model < ActiveRecord::Base
|
16
|
+
dalliance :process_method
|
17
|
+
end
|
18
|
+
|
19
|
+
process_method is the name of the method to invoke for background processing
|
20
|
+
to kick it off just call dalliance_background_process
|
21
|
+
|
22
|
+
Handle your migrations:
|
23
|
+
|
24
|
+
rails g dalliance:progress_meter
|
25
|
+
|
26
|
+
rails g dalliance:update model_name
|
27
|
+
|
28
|
+
== ProgressMeter
|
29
|
+
|
30
|
+
Create a method called dalliance_progress_meter_total_count
|
31
|
+
(or provide the dalliance_progress_meter_total_count_method option)
|
32
|
+
|
33
|
+
Inside process_method call progress_meter.increment! after each iteration
|
34
|
+
|
35
|
+
In your views you can then call dalliance_progress to get feedback on your asynchronous process
|
36
|
+
|
37
|
+
== Copyright
|
38
|
+
|
39
|
+
Copyright (c) 2012 Annkissam. See LICENSE for details.
|
data/Rakefile
ADDED
data/dalliance.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dalliance/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dalliance"
|
7
|
+
s.version = Dalliance::VERSION::STRING
|
8
|
+
s.authors = ["Eric Sullivan"]
|
9
|
+
s.email = ["eric.sullivan@annkissam.com"]
|
10
|
+
s.homepage = "https://github.com/annkissam/dalliance"
|
11
|
+
s.summary = Dalliance::VERSION::SUMMARY
|
12
|
+
s.description = %q{ Opinionated background processing for ActiveRecord w/ delayed_job & state_machine }
|
13
|
+
|
14
|
+
s.rubyforge_project = "dalliance"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency('activerecord', '>= 3.0.0')
|
22
|
+
s.add_dependency('activesupport', '>= 3.0.0')
|
23
|
+
|
24
|
+
s.add_dependency('delayed_job', '>= 2.0.0')
|
25
|
+
s.add_dependency('state_machine')
|
26
|
+
|
27
|
+
s.add_development_dependency 'rspec'
|
28
|
+
s.add_development_dependency 'delayed_job_active_record'
|
29
|
+
s.add_development_dependency 'sqlite3'
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Dalliance
|
4
|
+
class ProgressMeter < ::ActiveRecord::Base
|
5
|
+
self.table_name = 'dalliance_progress_meters'
|
6
|
+
|
7
|
+
belongs_to :dalliance_progress_model, :polymorphic => true
|
8
|
+
|
9
|
+
validates_presence_of :dalliance_progress_model
|
10
|
+
|
11
|
+
#current_count should max out at total_count, but we'll allow you to miscount...
|
12
|
+
validates_numericality_of :current_count, :only_integer => true, :greater_than_or_equal_to => 0#, :less_than_or_equal_to => Proc.new(&:total_count)
|
13
|
+
validates_numericality_of :total_count, :only_integer => true, :greater_than => 0
|
14
|
+
validates_numericality_of :progress, :only_integer => true, :greater_than_or_equal_to => 0, :less_than_or_equal_to => 100
|
15
|
+
|
16
|
+
def current_count
|
17
|
+
self[:current_count] ||= 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def total_count
|
21
|
+
self[:total_count] ||= 1
|
22
|
+
end
|
23
|
+
|
24
|
+
before_validation :calculate_progress
|
25
|
+
|
26
|
+
def calculate_progress
|
27
|
+
begin
|
28
|
+
self.progress = (current_count.to_f / total_count.to_f * 100).to_i
|
29
|
+
|
30
|
+
#Handle an incorrect total_count...
|
31
|
+
self.progress = 100 if progress > 100
|
32
|
+
rescue
|
33
|
+
#what, are you diving by zero?
|
34
|
+
self.progress = 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def increment!
|
39
|
+
self.current_count += 1
|
40
|
+
self.save!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/dalliance.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'dalliance/version'
|
2
|
+
|
3
|
+
require 'dalliance/progress_meter'
|
4
|
+
|
5
|
+
module Dalliance
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def options
|
10
|
+
@options ||= {
|
11
|
+
:background_processing => true,
|
12
|
+
:dalliance_progress_meter_total_count_method => :dalliance_progress_meter_total_count
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def background_processing?
|
17
|
+
options[:background_processing]
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure
|
21
|
+
yield(self) if block_given?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
included do
|
26
|
+
has_one :dalliance_progress_meter, :as => :dalliance_progress_model, :class_name => '::Dalliance::ProgressMeter'
|
27
|
+
|
28
|
+
serialize :dalliance_error_hash, Hash
|
29
|
+
|
30
|
+
#BEGIN state_machine(s)
|
31
|
+
scope :dalliance_pending, where(:dalliance_status => 'pending')
|
32
|
+
scope :dalliance_processing, where(:dalliance_status => 'processing')
|
33
|
+
scope :dalliance_processing_error, where(:dalliance_status => 'processing_error')
|
34
|
+
scope :dalliance_completed, where(:dalliance_status => 'completed')
|
35
|
+
|
36
|
+
state_machine :dalliance_status, :initial => :pending do
|
37
|
+
state :pending
|
38
|
+
state :processing
|
39
|
+
state :processing_error
|
40
|
+
state :completed
|
41
|
+
|
42
|
+
event :queue_dalliance do
|
43
|
+
transition :processing_error => :pending
|
44
|
+
end
|
45
|
+
|
46
|
+
event :start_dalliance do
|
47
|
+
transition :pending => :processing
|
48
|
+
end
|
49
|
+
|
50
|
+
event :error_dalliance do
|
51
|
+
transition :processing => :processing_error
|
52
|
+
end
|
53
|
+
|
54
|
+
event :finish_dalliance do
|
55
|
+
transition :processing => :completed
|
56
|
+
end
|
57
|
+
end
|
58
|
+
#END state_machine(s)
|
59
|
+
end
|
60
|
+
|
61
|
+
module ClassMethods
|
62
|
+
def dalliance_status_in_load_select_array
|
63
|
+
state_machine(:dalliance_status).states.map {|state| [state.human_name, state.name] }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#Force backgound_processing w/ true
|
68
|
+
def dalliance_background_process(backgound_processing = nil)
|
69
|
+
if backgound_processing || (backgound_processing.nil? && Dalliance.background_processing?)
|
70
|
+
delay.dalliance_process(true)
|
71
|
+
else
|
72
|
+
dalliance_process(false)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#backgound_processing == false will re-raise any exceptions
|
77
|
+
def dalliance_process(backgound_processing = false)
|
78
|
+
begin
|
79
|
+
start_dalliance!
|
80
|
+
|
81
|
+
build_dalliance_progress_meter(:total_count => calculate_dalliance_progress_meter_total_count).save!
|
82
|
+
|
83
|
+
self.send(self.class.dalliance_options[:dalliance_method])
|
84
|
+
|
85
|
+
finish_dalliance!
|
86
|
+
rescue StandardError => e
|
87
|
+
#Save the error for future analysis...
|
88
|
+
self.dalliance_error_hash = {:error => e, :message => e.message, :backtrace => e.backtrace}
|
89
|
+
|
90
|
+
error_dalliance!
|
91
|
+
|
92
|
+
#Don't raise the error if we're backgound_processing...
|
93
|
+
raise e unless backgound_processing
|
94
|
+
ensure
|
95
|
+
if dalliance_progress_meter
|
96
|
+
dalliance_progress_meter.destroy
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def dalliance_progress
|
102
|
+
if completed?
|
103
|
+
100
|
104
|
+
else
|
105
|
+
if dalliance_progress_meter
|
106
|
+
dalliance_progress_meter.progress
|
107
|
+
else
|
108
|
+
0
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#If the progress_meter_total_count_method is not implemented just use 1...
|
114
|
+
def calculate_dalliance_progress_meter_total_count
|
115
|
+
if respond_to?(self.class.dalliance_options[:dalliance_progress_meter_total_count_method])
|
116
|
+
self.send(self.class.dalliance_options[:dalliance_progress_meter_total_count_method])
|
117
|
+
else
|
118
|
+
1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
#http://yehudakatz.com/2009/11/12/better-ruby-idioms/
|
124
|
+
class ActiveRecord::Base
|
125
|
+
def self.dalliance(*args)
|
126
|
+
options = args.last.is_a?(Hash) ? Dalliance.options.merge(args.pop) : Dalliance.options
|
127
|
+
|
128
|
+
case args.length
|
129
|
+
when 1
|
130
|
+
options[:dalliance_method] = args[0]
|
131
|
+
else
|
132
|
+
raise ArgumentError, "Incorrect number of Arguements provided"
|
133
|
+
end
|
134
|
+
|
135
|
+
cattr_accessor :dalliance_options
|
136
|
+
self.dalliance_options = options
|
137
|
+
include Dalliance
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module Dalliance
|
5
|
+
class ProgressMeterGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
desc "Create a migration to add dalliance_progress_meters"
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
@source_root ||= File.expand_path('../templates', __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.next_migration_number(path)
|
15
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_migration
|
19
|
+
migration_template 'migration.rb', 'db/migrate/create_dalliance_progress_meters'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateDallianceProgressMeters < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :dalliance_progress_meters do |t|
|
4
|
+
t.belongs_to :dalliance_progress_model, :polymorphic => true
|
5
|
+
|
6
|
+
t.integer :current_count
|
7
|
+
t.integer :total_count
|
8
|
+
t.integer :progress
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :dalliance_progress_meters, [:dalliance_progress_model_id, :dalliance_progress_model_type], :name => 'by_dalliance_progress_model'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.down
|
17
|
+
remove_index :dalliance_progress_meters, :name => 'by_dalliance_progress_model'
|
18
|
+
|
19
|
+
drop_table :dalliance_progress_meters
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :<%= name.underscore.camelize.tableize %>, :dalliance_error_hash, :text
|
4
|
+
add_column :<%= name.underscore.camelize.tableize %>, :dalliance_status, :string, :null => false, :default => 'pending'
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_column :<%= name.underscore.camelize.tableize %>, :dalliance_error_hash
|
9
|
+
remove_column :<%= name.underscore.camelize.tableize %>, :dalliance_status
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#Adapted from paperclip...
|
2
|
+
#https://github.com/thoughtbot/paperclip
|
3
|
+
|
4
|
+
require 'rails/generators/active_record'
|
5
|
+
|
6
|
+
module Dalliance
|
7
|
+
class UpdateGenerator < ActiveRecord::Generators::Base
|
8
|
+
desc "Create a migration to add dalliance-specific fields to your model. " +
|
9
|
+
"The NAME argument is the name of your model"
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
@source_root ||= File.expand_path('../templates', __FILE__)
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_migration
|
16
|
+
migration_template "migration.rb.erb", "db/migrate/#{migration_file_name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def migration_name
|
22
|
+
"add_dalliance_to_#{name.underscore}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def migration_file_name
|
26
|
+
"#{migration_name}.rb"
|
27
|
+
end
|
28
|
+
|
29
|
+
def migration_class_name
|
30
|
+
migration_name.camelize
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DallianceModel do
|
4
|
+
subject { DallianceModel.create }
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Dalliance.options[:background_processing] = true
|
8
|
+
end
|
9
|
+
|
10
|
+
context "success" do
|
11
|
+
before(:all) do
|
12
|
+
DallianceModel.dalliance_options[:dalliance_method] = :dalliance_success_method
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should not call the dalliance_method w/o a Delayed::Worker" do
|
16
|
+
subject.dalliance_background_process
|
17
|
+
subject.reload
|
18
|
+
|
19
|
+
subject.should_not be_successful
|
20
|
+
Delayed::Job.count.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should call the dalliance_method w/ a Delayed::Worker" do
|
24
|
+
subject.dalliance_background_process
|
25
|
+
Delayed::Worker.new.work_off
|
26
|
+
subject.reload
|
27
|
+
|
28
|
+
subject.should be_successful
|
29
|
+
Delayed::Job.count.should == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should set the dalliance_status to completed" do
|
33
|
+
subject.dalliance_background_process
|
34
|
+
Delayed::Worker.new.work_off
|
35
|
+
subject.reload
|
36
|
+
|
37
|
+
subject.should be_completed
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should set the dalliance_progress to 100" do
|
41
|
+
subject.dalliance_background_process
|
42
|
+
Delayed::Worker.new.work_off
|
43
|
+
subject.reload
|
44
|
+
|
45
|
+
subject.dalliance_progress.should == 100
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "raise error" do
|
50
|
+
before(:all) do
|
51
|
+
DallianceModel.dalliance_options[:dalliance_method] = :dalliance_error_method
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should NOT raise an error" do
|
55
|
+
subject.dalliance_background_process
|
56
|
+
|
57
|
+
Delayed::Worker.new.work_off
|
58
|
+
|
59
|
+
Delayed::Job.count.should == 0
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should store the error" do
|
63
|
+
subject.dalliance_background_process
|
64
|
+
Delayed::Worker.new.work_off
|
65
|
+
subject.reload
|
66
|
+
|
67
|
+
subject.dalliance_error_hash.should_not be_empty
|
68
|
+
subject.dalliance_error_hash[:error].should == RuntimeError.new
|
69
|
+
subject.dalliance_error_hash[:message].should == 'RuntimeError'
|
70
|
+
subject.dalliance_error_hash[:backtrace].should_not be_blank
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should set the dalliance_status to processing_error" do
|
74
|
+
subject.dalliance_background_process
|
75
|
+
Delayed::Worker.new.work_off
|
76
|
+
subject.reload
|
77
|
+
|
78
|
+
subject.should be_processing_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should set the dalliance_progress to 0" do
|
82
|
+
subject.dalliance_background_process
|
83
|
+
Delayed::Worker.new.work_off
|
84
|
+
subject.reload
|
85
|
+
|
86
|
+
subject.dalliance_progress.should == 0
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DallianceModel do
|
4
|
+
subject { DallianceModel.create }
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Dalliance.options[:background_processing] = false
|
8
|
+
end
|
9
|
+
|
10
|
+
context "success" do
|
11
|
+
before(:all) do
|
12
|
+
DallianceModel.dalliance_options[:dalliance_method] = :dalliance_success_method
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should call the dalliance_method" do
|
16
|
+
lambda { subject.dalliance_background_process }.should change(subject, :successful).from(false).to(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set the dalliance_status to completed" do
|
20
|
+
lambda { subject.dalliance_background_process }.should change(subject, :dalliance_status).from('pending').to('completed')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set the dalliance_progress to 100" do
|
24
|
+
lambda { subject.dalliance_background_process }.should change(subject, :dalliance_progress).from(0).to(100)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "raise error" do
|
29
|
+
before(:all) do
|
30
|
+
DallianceModel.dalliance_options[:dalliance_method] = :dalliance_error_method
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise an error" do
|
34
|
+
expect { subject.dalliance_background_process }.to raise_error(RuntimeError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should store the error" do
|
38
|
+
expect { subject.dalliance_background_process }.to raise_error(RuntimeError)
|
39
|
+
|
40
|
+
subject.dalliance_error_hash.should_not be_empty
|
41
|
+
subject.dalliance_error_hash[:error].should == RuntimeError.new
|
42
|
+
subject.dalliance_error_hash[:message].should == 'RuntimeError'
|
43
|
+
subject.dalliance_error_hash[:backtrace].should_not be_blank
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set the dalliance_status to processing_error" do
|
47
|
+
expect { subject.dalliance_background_process }.to raise_error(RuntimeError)
|
48
|
+
|
49
|
+
subject.should be_processing_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should set the dalliance_progress to 0" do
|
53
|
+
expect { subject.dalliance_background_process }.to raise_error(RuntimeError)
|
54
|
+
|
55
|
+
subject.dalliance_progress.should == 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
#Automatically included in a rails app...
|
5
|
+
require 'active_support'
|
6
|
+
require 'state_machine'
|
7
|
+
require 'delayed_job'
|
8
|
+
|
9
|
+
#Required for testing...
|
10
|
+
require 'delayed_job_active_record'
|
11
|
+
|
12
|
+
require 'dalliance'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
#http://blog.rubyhead.com/2010/04/27/database-during-tests/
|
16
|
+
config.before do
|
17
|
+
ActiveRecord::Base.connection.begin_db_transaction
|
18
|
+
ActiveRecord::Base.connection.increment_open_transactions
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after do
|
22
|
+
if ActiveRecord::Base.connection.open_transactions != 0
|
23
|
+
ActiveRecord::Base.connection.rollback_db_transaction
|
24
|
+
ActiveRecord::Base.connection.decrement_open_transactions
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#We don't need a full rails app to test...
|
30
|
+
require 'support/active_record'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#Adapted from delayed_job_active_record
|
2
|
+
#https://github.com/collectiveidea/delayed_job_active_record
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
5
|
+
ActiveRecord::Migration.verbose = false
|
6
|
+
|
7
|
+
ActiveRecord::Schema.define do
|
8
|
+
create_table :dalliance_progress_meters, :force => true do |t|
|
9
|
+
t.belongs_to :dalliance_progress_model, :polymorphic => true
|
10
|
+
|
11
|
+
t.integer :current_count
|
12
|
+
t.integer :total_count
|
13
|
+
t.integer :progress
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
add_index :dalliance_progress_meters, [:dalliance_progress_model_id, :dalliance_progress_model_type], :name => 'by_dalliance_progress_model'
|
19
|
+
|
20
|
+
create_table :delayed_jobs, :force => true do |table|
|
21
|
+
table.integer :priority, :default => 0
|
22
|
+
table.integer :attempts, :default => 0
|
23
|
+
table.text :handler
|
24
|
+
table.text :last_error
|
25
|
+
table.datetime :run_at
|
26
|
+
table.datetime :locked_at
|
27
|
+
table.datetime :failed_at
|
28
|
+
table.string :locked_by
|
29
|
+
table.string :queue
|
30
|
+
table.timestamps
|
31
|
+
end
|
32
|
+
|
33
|
+
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
34
|
+
|
35
|
+
create_table :dalliance_models, :force => true do |t|
|
36
|
+
t.text :dalliance_error_hash
|
37
|
+
t.string :dalliance_status, :string, :null => false, :default => 'pending'
|
38
|
+
|
39
|
+
t.boolean :successful, :default => false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Purely useful for test cases...
|
44
|
+
class DallianceModel < ActiveRecord::Base
|
45
|
+
dalliance :dalliance_success_method
|
46
|
+
|
47
|
+
def dalliance_success_method
|
48
|
+
update_attribute(:successful, true)
|
49
|
+
end
|
50
|
+
|
51
|
+
def dalliance_error_method
|
52
|
+
raise RuntimeError
|
53
|
+
end
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dalliance
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Sullivan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70098455466720 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70098455466720
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &70098455466100 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70098455466100
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: delayed_job
|
38
|
+
requirement: &70098455465500 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70098455465500
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: state_machine
|
49
|
+
requirement: &70098455465020 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70098455465020
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rspec
|
60
|
+
requirement: &70098455464440 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70098455464440
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: delayed_job_active_record
|
71
|
+
requirement: &70098455463520 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70098455463520
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: sqlite3
|
82
|
+
requirement: &70098455462940 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70098455462940
|
91
|
+
description: ! ' Opinionated background processing for ActiveRecord w/ delayed_job
|
92
|
+
& state_machine '
|
93
|
+
email:
|
94
|
+
- eric.sullivan@annkissam.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- .rspec
|
101
|
+
- Gemfile
|
102
|
+
- LICENSE
|
103
|
+
- README.rdoc
|
104
|
+
- Rakefile
|
105
|
+
- dalliance.gemspec
|
106
|
+
- lib/dalliance.rb
|
107
|
+
- lib/dalliance/progress_meter.rb
|
108
|
+
- lib/dalliance/version.rb
|
109
|
+
- lib/generators/dalliance/progress_meter/progress_meter_generator.rb
|
110
|
+
- lib/generators/dalliance/progress_meter/templates/migration.rb
|
111
|
+
- lib/generators/dalliance/update/templates/migration.rb.erb
|
112
|
+
- lib/generators/dalliance/update/update_generator.rb
|
113
|
+
- spec/dalliance/asynchronous_spec.rb
|
114
|
+
- spec/dalliance/dalliance_spec.rb
|
115
|
+
- spec/dalliance/synchronous_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- spec/support/active_record.rb
|
118
|
+
homepage: https://github.com/annkissam/dalliance
|
119
|
+
licenses: []
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ! '>='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project: dalliance
|
138
|
+
rubygems_version: 1.8.10
|
139
|
+
signing_key:
|
140
|
+
specification_version: 3
|
141
|
+
summary: dalliance 0.0.1
|
142
|
+
test_files:
|
143
|
+
- spec/dalliance/asynchronous_spec.rb
|
144
|
+
- spec/dalliance/dalliance_spec.rb
|
145
|
+
- spec/dalliance/synchronous_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/support/active_record.rb
|