Skip to content

Commit

Permalink
feat: record method
Browse files Browse the repository at this point in the history
  • Loading branch information
phortx committed Oct 7, 2021
1 parent f381417 commit 62daf4d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,19 @@ The error_code can also passed as first argument to the `failure` step definitio

### Record

The UseCase should assign the main record to `@record`. Calling `save!` without argument will try to
save that record or raises an exception. Also the `@record` will automatically passed into the outcome.
The UseCase should assign the main record to `@record`. Calling `save!` without
argument will try to save that record or raises an exception. Also the
`@record` will automatically passed into the outcome.

You can either set the `@record` manually or via the `record` method. This comes
in two flavors:

Either passing the name of a param as symbol. Let's assume the UseCase
has a parameter called `user` (defined via `attr_accessor`), then you can assign
the user to `@record` by adding `record :user` to your use case.

The alternative way is to pass a block which returns the value for `@record`
like in the example UseCase below.


### Example UseCase
Expand All @@ -81,16 +92,18 @@ class BlogPosts::Create < Rails::UseCase
validates :content, presence: true
validates :author, presence: true

record { BlogPost.new }

failure :access_denied, message: 'No permission', unless: -> { author.can_publish_blog_posts? }
step :build_post
step :assign_attributes
step :save!
succeed unless: -> { publish }
step :publish, do: -> { record.publish! }
step :notify_subscribers, unless: -> { skip_notifications }


private def build_post
@record = BlogPost.new(
private def assign_attributes
@record.assign_attributes(
title: title,
content: content,
created_by: author,
Expand Down
16 changes: 16 additions & 0 deletions lib/rails/use_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,24 @@ def self.with(mod)
end


# DSL to set the record source.
# @param [Symbol|nil] Name of the param.
# @yields
def self.record(param = nil, &block)
block = -> { send(param.to_sym) } unless block_given?

define_method(:determine_record, &block)
end


# Will run the steps of the use case.
def process
@record = determine_record if respond_to?(:determine_record)
run_steps
end


def run_steps
self.class.steps.each do |step|
# Check wether to skip when :if or :unless are set.
next if skip_step?(step)
Expand Down
20 changes: 19 additions & 1 deletion spec/rails/use_case_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ class UseCaseTestImpl < Rails::UseCase

validates :order, presence: true

record :order

step :do_things
step { record.bar }

def do_things
@record = order
true
end
end

Expand Down Expand Up @@ -108,6 +110,8 @@ class UseCaseTestImplSkipUnless < Rails::UseCase

def do_things
@record = order

record.bar
end

def dont_do_this
Expand All @@ -121,6 +125,8 @@ class UseCaseTestImplSuccess < Rails::UseCase

validates :order, presence: true

record { 42 }

success
step :do_things

Expand Down Expand Up @@ -218,6 +224,18 @@ def do_things
expect(UseCaseTestImplSuccess.call(order: order)).to be_success
end

it 'can have a record definition with a symbol' do
outcome = UseCaseTestImpl.call(order: order)
expect(outcome).to be_success
expect(outcome.record).to eq(order)
end

it 'can have a record definition with a block' do
outcome = UseCaseTestImplSuccess.call(order: order)
expect(outcome).to be_success
expect(outcome.record).to eq(42)
end

it 'can have a failure step' do
expect_any_instance_of(UseCaseTestImplFailure).not_to \
receive(:do_things)
Expand Down

0 comments on commit 62daf4d

Please sign in to comment.