@@ -44,6 +44,7 @@ gem 'simple_form' |
||
44 | 44 |
gem 'bootstrap_form' |
45 | 45 |
gem 'friendly_id', '~> 5.0.0' |
46 | 46 |
gem 'devise' |
47 |
+gem "devise-async" |
|
47 | 48 |
gem "letter_opener", :group => :development |
48 | 49 |
gem 'redcarpet' |
49 | 50 |
gem 'summernote-rails' |
@@ -71,6 +71,8 @@ GEM |
||
71 | 71 |
railties (>= 3.2.6, < 5) |
72 | 72 |
thread_safe (~> 0.1) |
73 | 73 |
warden (~> 1.2.3) |
74 |
+ devise-async (0.9.0) |
|
75 |
+ devise (~> 3.2) |
|
74 | 76 |
diff-lcs (1.2.5) |
75 | 77 |
email_spec (1.6.0) |
76 | 78 |
launchy (~> 2.1) |
@@ -291,6 +293,7 @@ DEPENDENCIES |
||
291 | 293 |
cucumber-rails |
292 | 294 |
database_cleaner |
293 | 295 |
devise |
296 |
+ devise-async |
|
294 | 297 |
email_spec |
295 | 298 |
factory_girl_rails (~> 4.0) |
296 | 299 |
figaro |
@@ -1,7 +1,7 @@ |
||
1 | 1 |
class User < ActiveRecord::Base |
2 | 2 |
# Include default devise modules. Others available are: |
3 | 3 |
# :confirmable, :lockable, :timeoutable and :omniauthable |
4 |
- devise :database_authenticatable, :registerable, |
|
4 |
+ devise :database_authenticatable, :async, :registerable, |
|
5 | 5 |
:recoverable, :rememberable, :trackable, :validatable |
6 | 6 |
|
7 | 7 |
validates :password, presence: true, length: {minimum: 5, maximum: 120}, on: :create |
@@ -6,7 +6,7 @@ class SubscribeToMailchimp |
||
6 | 6 |
# Get User |
7 | 7 |
subscription = Subscription.find_by_id(id) |
8 | 8 |
|
9 |
- return true if (Rails.env.test? && !testing) |
|
9 |
+ return true if (Rails.env.test?) |
|
10 | 10 |
list_id = ENV['MAILCHIMP_LIST_ID'] |
11 | 11 |
response = Rails.configuration.mailchimp.lists.subscribe({ |
12 | 12 |
id: list_id, |
@@ -0,0 +1,2 @@ |
||
1 |
+# require "#{Rails.root}/features/support/cucumber_external_resque_worker" |
|
2 |
+# CucumberExternalResqueWorker.install_hooks_on_startup |
@@ -13,7 +13,7 @@ Devise.setup do |config| |
||
13 | 13 |
config.mailer_sender = ENV['SERVER_EMAIL'] |
14 | 14 |
|
15 | 15 |
# Configure the class responsible to send e-mails. |
16 |
- # config.mailer = 'Devise::Mailer' |
|
16 |
+ #config.mailer = 'Devise::Mailer' |
|
17 | 17 |
|
18 | 18 |
# ==> ORM configuration |
19 | 19 |
# Load and configure the ORM. Supports :active_record (default) and |
@@ -0,0 +1,6 @@ |
||
1 |
+# config/initializers/devise_async.rb |
|
2 |
+Devise::Async.setup do |config| |
|
3 |
+ config.enabled = true |
|
4 |
+ config.backend = :resque |
|
5 |
+ config.queue = :send_reset_password |
|
6 |
+end |
@@ -0,0 +1 @@ |
||
1 |
+Resque.inline = Rails.env.test? |
@@ -60,6 +60,9 @@ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([ |
||
60 | 60 |
# @email = ActionMailer::Base.deliveries.last |
61 | 61 |
# @email.to.should include address |
62 | 62 |
# @email.subject.should subject |
63 |
+ # CucumberExternalResqueWorker.reset_counter |
|
64 |
+ # Resque.remove_queue(:send_contact_message_queue) |
|
65 |
+ # CucumberExternalResqueWorker.process_all |
|
63 | 66 |
unread_emails_for(address).select { |m| m.subject =~ Regexp.new(Regexp.escape(subject)) }.size.should == parse_email_count(amount) |
64 | 67 |
end |
65 | 68 |
|
@@ -0,0 +1,125 @@ |
||
1 |
+# This is adapted from this gist: https://gist.github.com/532100 by Square |
|
2 |
+# The main difference is that it doesn't require Bluth for WorkerBase |
|
3 |
+# It also calls prune_dead_workers on start so it doesn't hang on every other run |
|
4 |
+# It does not do anything special to avoid connecting to your main redis instance; you should be |
|
5 |
+# doing that elsewhere |
|
6 |
+ |
|
7 |
+class CucumberExternalResqueWorker |
|
8 |
+ DEFAULT_STARTUP_TIMEOUT = 1.minute |
|
9 |
+ COUNTER_KEY = "cucumber:counter" |
|
10 |
+ |
|
11 |
+ class << self |
|
12 |
+ attr_accessor :pid, :startup_timeout |
|
13 |
+ |
|
14 |
+ def start |
|
15 |
+ # Call from a Cucumber support file so it is run on startup |
|
16 |
+ return unless Rails.env.test? |
|
17 |
+ if self.pid = fork |
|
18 |
+ start_parent |
|
19 |
+ wait_for_worker_to_start |
|
20 |
+ else |
|
21 |
+ start_child |
|
22 |
+ end |
|
23 |
+ end |
|
24 |
+ |
|
25 |
+ def install_hooks_on_startup |
|
26 |
+ # Call from a Rails initializer |
|
27 |
+ return unless Rails.env.test? |
|
28 |
+ # Because otherwise crashed workers cause a fork and we pause the actual worker forever |
|
29 |
+ Resque::Worker.all.each { |worker| worker.prune_dead_workers } |
|
30 |
+ install_pause_on_start_hook |
|
31 |
+ install_worker_base_counter_patch |
|
32 |
+ end |
|
33 |
+ |
|
34 |
+ def process_all |
|
35 |
+ # Call from a Cucumber step |
|
36 |
+ unpause |
|
37 |
+ sleep 1 until done? |
|
38 |
+ pause |
|
39 |
+ end |
|
40 |
+ |
|
41 |
+ def incr |
|
42 |
+ Resque.redis.incr(COUNTER_KEY) |
|
43 |
+ end |
|
44 |
+ |
|
45 |
+ def decr |
|
46 |
+ Resque.redis.decr(COUNTER_KEY) |
|
47 |
+ end |
|
48 |
+ |
|
49 |
+ def reset_counter |
|
50 |
+ Resque.redis.set(COUNTER_KEY, 0) |
|
51 |
+ end |
|
52 |
+ |
|
53 |
+ private |
|
54 |
+ |
|
55 |
+ def done? |
|
56 |
+ Resque.redis.get(CucumberExternalResqueWorker::COUNTER_KEY).to_i.zero? |
|
57 |
+ end |
|
58 |
+ |
|
59 |
+ def pause(pid = self.pid) |
|
60 |
+ return unless Rails.env.test? |
|
61 |
+ Process.kill("USR2", pid) |
|
62 |
+ end |
|
63 |
+ |
|
64 |
+ def unpause |
|
65 |
+ return unless Rails.env.test? |
|
66 |
+ Process.kill("CONT", pid) |
|
67 |
+ end |
|
68 |
+ |
|
69 |
+ def start_parent |
|
70 |
+ at_exit do |
|
71 |
+ #reset_counter |
|
72 |
+ Process.kill("KILL", pid) if pid |
|
73 |
+ end |
|
74 |
+ end |
|
75 |
+ |
|
76 |
+ def start_child |
|
77 |
+ # Array form of exec() is required here, otherwise the worker is not a direct child process of cucumber. |
|
78 |
+ # If it's not the direct child process then the PID returned from fork() is wrong, which means we can't |
|
79 |
+ # communicate with the worker. |
|
80 |
+ exec('rake', 'resque:work', "QUEUE=*", "RAILS_ENV=test", "VVERBOSE=1") |
|
81 |
+ end |
|
82 |
+ |
|
83 |
+ def wait_for_worker_to_start |
|
84 |
+ self.startup_timeout ||= DEFAULT_STARTUP_TIMEOUT |
|
85 |
+ start = Time.now.to_i |
|
86 |
+ while (Time.now.to_i - start) < startup_timeout |
|
87 |
+ return if worker_started? |
|
88 |
+ sleep 1 |
|
89 |
+ end |
|
90 |
+ |
|
91 |
+ raise "Timeout while waiting for the worker to start. Waited #{startup_timeout} seconds." |
|
92 |
+ end |
|
93 |
+ |
|
94 |
+ def worker_started? |
|
95 |
+ Resque.info[:workers].to_i > 0 |
|
96 |
+ end |
|
97 |
+ |
|
98 |
+ def install_pause_on_start_hook |
|
99 |
+ Resque.before_first_fork do |
|
100 |
+ #reset_counter |
|
101 |
+ pause(Process.pid) |
|
102 |
+ end |
|
103 |
+ end |
|
104 |
+ |
|
105 |
+ def install_worker_base_counter_patch |
|
106 |
+ Resque.class_eval do |
|
107 |
+ class << self |
|
108 |
+ def enqueue_with_counters(*args, &block) |
|
109 |
+ CucumberExternalResqueWorker.incr |
|
110 |
+ enqueue_without_counters(*args, &block) |
|
111 |
+ end |
|
112 |
+ alias_method_chain :enqueue, :counters |
|
113 |
+ end |
|
114 |
+ end |
|
115 |
+ Resque::Job.class_eval do |
|
116 |
+ def perform_with_counters(*args, &block) |
|
117 |
+ perform_without_counters(*args, &block) |
|
118 |
+ ensure |
|
119 |
+ CucumberExternalResqueWorker.decr |
|
120 |
+ end |
|
121 |
+ alias_method_chain :perform, :counters |
|
122 |
+ end |
|
123 |
+ end |
|
124 |
+ end |
|
125 |
+end |
@@ -6,6 +6,9 @@ |
||
6 | 6 |
|
7 | 7 |
require 'cucumber/rails' |
8 | 8 |
|
9 |
+# require "#{Rails.root}/features/support/cucumber_external_resque_worker" |
|
10 |
+# CucumberExternalResqueWorker.start |
|
11 |
+ |
|
9 | 12 |
# Capybara defaults to CSS3 selectors rather than XPath. |
10 | 13 |
# If you'd prefer to use XPath, just uncomment this line and adjust any |
11 | 14 |
# selectors in your step definitions to use the XPath syntax. |
@@ -31,7 +34,7 @@ ActionController::Base.allow_rescue = false |
||
31 | 34 |
# Remove/comment out the lines below if your app doesn't have a database. |
32 | 35 |
# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead. |
33 | 36 |
begin |
34 |
- DatabaseCleaner.strategy = :transaction |
|
37 |
+ DatabaseCleaner.strategy = :truncation |
|
35 | 38 |
rescue NameError |
36 | 39 |
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." |
37 | 40 |
end |
@@ -66,3 +69,5 @@ require "#{Rails.root}/spec/spec_helper" |
||
66 | 69 |
ActionMailer::Base.delivery_method = :test |
67 | 70 |
ActionMailer::Base.perform_deliveries = true |
68 | 71 |
ActionMailer::Base.deliveries.clear |
72 |
+ |
|
73 |
+ |