Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pending ActionableError #37

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Added `.DS_Store` to `.gitignore`
- Added support for Rails > 5
- Added support for Rails > 6
- Add Onesie CheckPending page in development

### Changed
- Switch `colorize` gem for `rainbow`
Expand All @@ -20,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed `bpdocs.yml`
- Removed support for Ruby 2.6.x
- Removed debugging dependencies
- Removed support for Rails 4.x
- Removed support for Rails 4.x and 5.x

### Fixed
- Fix documentation formatting for MKDocs
Expand Down
10 changes: 10 additions & 0 deletions doc/how_to_guides/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,13 @@ bundle exec rake onesie:rerun['20220105140152_my_task'] # Reruns MyTask
```bash
rake onesies:describe # Prints a list of available onesies to run
```

## Onesie ActionableError
To enforce that pending onesie tasks are always run, enable the follow Rails
configuration in development.

```ruby
# config/environments/development.rb
config.onesie.task_error = :page_load`
```
Rails will now raise an ActionableError if there are pending onesies.
1 change: 1 addition & 0 deletions lib/onesie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require 'rainbow/refinement'

require_relative 'onesie/check_pending'
require_relative 'onesie/describe_tasks'
require_relative 'onesie/errors'
require_relative 'onesie/manager'
Expand Down
34 changes: 34 additions & 0 deletions lib/onesie/check_pending.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Onesie
# This class is used to verify that all onesie tasks have been run before
# loading a web page if `config.onesie.task_error` is set to `:page_load`.
# Influenced by ActiveRecord::Migration::CheckPending
class CheckPending
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
@app = app
@needs_check = true
@mutex = Mutex.new
@file_watcher = file_watcher
end

def call(env)
@mutex.synchronize do
@watcher ||= build_watcher do
@needs_check = true
Manager.check_pending!
@needs_check = false
end

@needs_check ? @watcher.execute : @watcher.execute_if_updated
end

@app.call(env)
end

private

def build_watcher(&block)
paths = Array(Manager.tasks_path)
@file_watcher.new([], paths, &block)
end
end
end
21 changes: 21 additions & 0 deletions lib/onesie/errors.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
# frozen_string_literal: true

require 'active_support'
require 'active_support/rails'

module Onesie
OnesieError = Class.new(StandardError)

class PendingTaskError < OnesieError # :nodoc:
include ActiveSupport::ActionableError

action 'Run pending Onesies' do
Onesie::Manager.new.run_all
end

def initialize(message = nil)
super(message || detailed_onesie_message)
end

private

def detailed_onesie_message
'Onesie Tasks are pending. To resolve this issue, run: rake onesie:run_all'
end
end

# Raised when there is no matching Task for the provided Task filename.
class TaskNotFoundError < OnesieError
def initialize(filename)
Expand Down
4 changes: 4 additions & 0 deletions lib/onesie/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class << self

self.tasks_path = 'onesie/tasks'

def self.check_pending!
raise PendingTaskError if new.pending_tasks?
end

def initialize(runner: Onesie::Runner)
@runner = runner
end
Expand Down
10 changes: 10 additions & 0 deletions lib/onesie/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

module Onesie
class Railtie < Rails::Railtie # :nodoc:
config.onesie = ActiveSupport::OrderedOptions.new

initializer 'onesie.task_error' do |app|
if config.onesie.task_error == :page_load
config.app_middleware.insert_after ::ActiveRecord::Migration::CheckPending,
Onesie::CheckPending,
file_watcher: app.config.file_watcher
end
end

rake_tasks do
load('onesie/tasks/onesie.rake')
end
Expand Down
4 changes: 2 additions & 2 deletions onesie.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']

spec.add_runtime_dependency 'activerecord', '> 5'
spec.add_runtime_dependency 'railties', '> 5'
spec.add_runtime_dependency 'activerecord', '> 6'
spec.add_runtime_dependency 'railties', '> 6'
spec.add_runtime_dependency 'rainbow', '~> 3'
end
28 changes: 28 additions & 0 deletions spec/onesie/manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@
allow(described_class).to receive(:tasks_path).and_return('spec/support/tasks')
end

describe '.check_pending!' do
let(:double) { instance_double(described_class) }

before do
allow(described_class).to receive(:new).and_return(double)
end

context 'when there are no pending tasks' do
before { allow(manager).to receive(:pending_tasks?).and_return(false) }

it 'does not raise an Error' do
expect {
described_class.check_pending!
}.not_to raise_error
end
end

context 'when there are pending tasks' do
before { allow(manager).to receive(:pending_tasks?).and_return(true) }

it 'raises a PendingTaskError' do
expect {
described_class.check_pending!
}.to raise_error(Onesie::PendingTaskError)
end
end
end

describe '#tasks' do
it 'returns an array of TaskProxies' do
expect(manager.tasks).to include(Onesie::TaskProxy)
Expand Down
Loading