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

NoResponseError #13

Merged
merged 1 commit into from
Jul 5, 2018
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added

- Started raising a `NoResponseError` if an operation doesn't return a `result.response` skill

## [2.2.0]

## Added
Expand Down
3 changes: 1 addition & 2 deletions lib/pragma/rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
require 'pragma/rails/version'
require 'pragma/rails/controller'
require 'pragma/rails/resource_controller'
require 'pragma/rails/errors'

require 'generators/pragma/resource_generator' if defined?(::Rails::Generators)

module Pragma
# Ruby on Rails integration for the Pragma architecture.
#
# @author Alessandro Desantis
module Rails
end
end
4 changes: 2 additions & 2 deletions lib/pragma/rails/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ module Pragma
module Rails
# This mixin should be included in a Rails controller to provide integration with Pragma
# operations.
#
# @author Alessandro Desantis
module Controller
def self.included(klass)
klass.include InstanceMethods
Expand All @@ -28,6 +26,8 @@ def run(operation_klass)
'policy.context' => policy_context
)

fail NoResponseError unless result['result.response']

result['result.response'].headers.each_pair do |key, value|
response.headers[key] = value
end
Expand Down
14 changes: 14 additions & 0 deletions lib/pragma/rails/errors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Pragma
module Rails
class NoResponseError < StandardError
def initialize
super <<~MESSAGE
Your operation did not return a `result.response` skill, which might mean one of the following:

* The execution of the operation halted early (maybe one of your steps returned a falsey value?).
* You forgot to set a `result.response` skill in a custom operation.
MESSAGE
end
end
end
end
2 changes: 0 additions & 2 deletions lib/pragma/rails/resource_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module Pragma
module Rails
# Exposes CRUD operations on a resource through a Rails controller.
#
# @author Alessandro Desantis
module ResourceController
def self.included(klass)
klass.include Controller
Expand Down
101 changes: 64 additions & 37 deletions spec/pragma/rails/controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,83 @@
RSpec.describe Pragma::Rails::Controller do
subject { controller_klass.new.tap(&:run_operation) }

let(:controller_klass) do
Class.new do
attr_reader :render_args

def run_operation
operation = Class.new(Pragma::Operation::Base) do
step :respond!

def respond!(options, params:, **)
options['result.response'] = Pragma::Operation::Response::Created.new(
headers: { 'X-Foo' => params[:foo] },
entity: { foo: params[:foo] }
)
context 'when the operation executes successfully' do
let(:controller_klass) do
Class.new do
attr_reader :render_args

def run_operation
operation = Class.new(Pragma::Operation::Base) do
step :respond!

def respond!(options, params:, **)
options['result.response'] = Pragma::Operation::Response::Created.new(
headers: { 'X-Foo' => params[:foo] },
entity: { foo: params[:foo] }
)
end
end

run operation
end

run operation
end
def response
@response ||= OpenStruct.new(headers: {})
end

def response
@response ||= OpenStruct.new(headers: {})
end
def render(*args)
@render_args = args
end

def render(*args)
@render_args = args
end
def params
{}
end

protected

def params
{}
def operation_params
ActionController::Parameters.new(foo: 'bar')
end
end.tap do |klass|
klass.include described_class
end
end

protected
it 'responds with the headers from the operation' do
expect(subject.response.headers).to eq('X-Foo' => 'bar')
end

def operation_params
ActionController::Parameters.new(foo: 'bar')
end
end.tap do |klass|
klass.include described_class
it 'responds with the status code from the operation' do
expect(subject.render_args.first[:status]).to eq(201)
end
end

it 'responds with the headers from the operation' do
expect(subject.response.headers).to eq('X-Foo' => 'bar')
it 'responds with the resource from the operation' do
expect(subject.render_args.first[:json]).to eq('foo' => 'bar')
end
end

it 'responds with the status code from the operation' do
expect(subject.render_args.first[:status]).to eq(201)
end
context 'when the operation does not set a result.response skill' do
let(:controller_klass) do
Class.new do
attr_reader :render_args

def run_operation
operation = Class.new(Pragma::Operation::Base)
run operation
end

it 'responds with the resource from the operation' do
expect(subject.render_args.first[:json]).to eq('foo' => 'bar')
protected

def operation_params
ActionController::Parameters.new(foo: 'bar')
end
end.tap do |klass|
klass.include described_class
end
end

it 'raises a NoResponseError' do
expect { subject }.to raise_error(Pragma::Rails::NoResponseError)
end
end
end