nebulab / simple_command

A simple, standardized way to build and use Service Objects (aka Commands) in Ruby
http://nebulab.it
MIT License
625 stars 55 forks source link

Allows passing a block to be executed when command succeeded #20

Closed jairovm closed 4 years ago

jairovm commented 5 years ago

Hi guys!

This small change is aimed to simplify controller logic, moving from something like this:

  def create
    command = AuthenticateUser.call(session_params[:email], session_params[:password])

    if command.success?
      redirect_to root_path
    else
      render :new
    end
  end

To this

  def create
    AuthenticateUser.call(session_params[:email], session_params[:password]) do
      # return keyword is key here to avoid `duplicate render/redirect error`
      return redirect_to root_path      
    end

    # executed only when command fails
    render :new
  end

The block passed to Command.call will be executed only when command is success

kennyadsl commented 5 years ago

Personally, I'm not sure about this. To save an if statement we are introducing a behavior that is not intuitive since you always have to remember to use return at the end of the block.

Also, there could be circumstances when you may want to not return since you have other code to be executed, for example, something that should happen after both successful and failing commands.

jairovm commented 5 years ago

@kennyadsl return keyword is only needed when you want to stop execution like might be the case when dealing with Controllers.

I agree with you, my example might not be the best one and remembering to use return adds some complexity.

But I think on this like adding a shortcut when you want something to be executed on success only and dont care about failures ( it might be useful when writing tests ).

AuthenticateUser.call(session_params[:email], session_params[:password]) do |command|
  do_something_with_command_object(command)
end

Passing a block is optional so if else way is still possible, besides doing something after command gets executed.

command = AuthenticateUser.call(session_params[:email], session_params[:password])

do_something_regardless_of_status(command)