dry.rb is a great collection of the “next-generation” libraries for your Ruby projects.
Of course, it’s not good for your next blog engine, but can be useful for big “enterprise” projects with complicated logic and data operations.
Let’s take a look for example for small API, which we use in our office for employees board, you can get all employees list as unauthenticated user, but to view full user’s profile, you need an account and JWT token. I would prefer to use some kind of CommandQuery Separation approach in this project.
So, let’s start.
We have a User model for example, and we use Devise for authentication.
We also have a app/commands directory, where we place our commands.
Or base command will be base_command.rb, we inherit all commands from this class.
Nothing special here, just include Dry::Transaction, class method run with params and block, and basic method for error handling.
We have ONE command for ONE action, and we start from sign_up_command.rb.
Steps here work like a steps in transactions - we just go step by step, and make a rollback if some step fails.
Next interesting thing is a Right and Left constructors from http://dry-rb.org/gems/dry-monads.
Let’s check docs, nothing special:
The Either monad is useful to express a series of computations that might return an error object with additional information. The Either mixin has two type constructors: Right and Left. The Right can be thought of as "everything went right" and the Left is used when "something has gone wrong".
And what we have in RegistrationsController ?
Pattern matching. Use the Either monad to model success and failure and match on the result.
Ok, great. But what if we want to get list of all created users?
We can use some query object here as usual.
Same here, simple steps, we just query for users and paginate it.
Then just call index_query method. Simple to write. Simple to test. Simple to understand.