Ruby on Rails - Trailblazer: A New Architecture for Rails - ruby on rails tutorial - rails guides - rails tutorial - ruby rails
Trailblazer:
- Trailblazer is a framework on top of Rails to serve as architectural guidance.
- It’s like a mesh-up of all the gems I’ve done before with some new concepts like operation, which will model every high-level domain action.
- A high-level domain operation, as I call it, is something like updating a comment, deleting a user, getting a list of all the recent comments, and so on.
- In essence, it encompasses everything the user can do through the user interface or via the API.
The Motivation
- For the last few years I’ve been hired from different companies to refactor messed up Rails applications, and one of the most common problems I’ve run into are legacy projects with huge models of PHP scripts put into a Ruby model, where all the domain, rendering, processing,
- Validation and etcetera are put in the model.
- Another one run into are horrible view layers, where the partials weren’t encapsulated and therefore every partial had access to every variable, which ends up in a messy view layer.
- The underlying cause of this problem is that there is no guidance in Rails architecture.
- For example, to me, using service objects is common sense, though for beginners it may be confusing.
- No one tells you where to use a service object and no one tells you how a service object looks like.
- Additionally, no one tells you about the API but if you read blogs, everyone says they use service objects and tells you to use one.
- Many of my friends who just started Rails keep asking me where they’re supposed to use a service object, form, model, and etcetera, so what I’m trying with Trailblazer is to bring structure to Rails where it will serve like a conventional structure to make it clear to the user what every step is. (E.g. which step is an operation, this step requires a form, and so on.)
Trailblazer Works:
Operations
Learn ruby - ruby tutorial - ruby trailazer work - ruby examples - ruby programs
- Although there are other features like view components, operation is the principle element of the Trailblazer.
- It works as the diagram above, in which you model this instead of pushing all of that functionality into one monolithic model.
- Therefore, you’ll have different operation passes for every step. Every operation has a contract, and the contract is a reform object.
- So, every object will have the same entry point and will use the contract to validate incoming data.
- Additionally, the operation can also present the validation to the viewer or API, and after that has happened, your actual domain logic is random.
- To give an example of how operation works, let’s say you click on a delete button.
- When you do that is you go to the control that knows a little bit of this action because it does authentication-if it’s valid it does one thing and if it’s not it does another thing. Instead of delegating to a model that has 10 lines of code delegating to different models and eventually ends up needing three layers of application code, the controller in the Trailblazer framework will delegate this delete action to a service object.
- You can have as many operations as you want.
- In order to use an operation in the controller, all I have to do is use the run method, in which all I have as a class is run.
- To make it obvious that this is an atomic set in your domain, def create
- The run method accepts a block which is only called when the operation is valid, which I think is pretty nifty.
This block
- Is yielded when valid, so if you use return in the block, you’re done-the controller action will finish and the request is done.
- If the operation is not valid, the code will carry on and run into the render block
Which is the response for handling an invalid operation stage.
- This will be a handy way of using the operation because you won’t need ifs and elses. You’ll simply have to use the block for a valid state and a return, and this will just jump out of the action or wherever you call it.
- There are different ways to call an operation, but this will cover 99% of the cases when you want to trigger domain logic in a controller this the “flow usage”. When you call run, a reform object, which I call a contract, is internally instantiated.
- A contract is instantiated because every object is a contract per definition-you don’t have to contract every operation
Reform in Trailblazer
- Reform is a pretty cool gem that validates data without touching the model, which allows me to define a field and the validation for the field, and I can use active models, unique validations and other things that are usually sitting in the model.
- However, it’s very explicit, so you’ll have to define the field(s), which can be nested, and you can also add methods to that contract.
- So, you can see in the code sample
This part of the operation covers the entire process of validation.
- Therefore, when you call create.run in the controller, it will jump into the process instant method.
- It’s the only method you’ll have to implement in an operation, and in that method, you can create whatever model(s) you need for that domain action step.
- Thus, if you want to create a new comment, you will call the built-in method validate as in the parameters and the model you created.
- This step will then instantiate the form object (e.g. validate), and then call the block with the form, which is valid then you’ll save the model in this block:
- contract.save # further after_save logic happens here
- Certainly, you can call other operations.