Form object pattern in Rails

Tram Ho

1.Previous

A form object is an object used to manage the complexity of data modification operations that goes beyond the basic CRUD functions. Usually, the basic CRUD tasks like adding users, editing users, or deleting users need very little code so we can put them in the controller. However, complexity arises when the function of creating a user requires creating an additional organization to add that user, or for an e-commerce application, if the user purchases a product, then an order and a payment transaction. must be created at the same time. Because the business logic is complicated, the number of lines of code as well as the objects created will be very large and will lead to a “fat controller” status. And a “fat controller” will be difficult to test as well as maintain, complex logic will lead you to write many test cases, but usually the controller also requires authentication and authorization, so when testing we still need Must create more data to pass authentication and authorization for the other test cases, this is redundant and can slow down the test.

Another downside is that the business logic won’t be reusable elsewhere because it’s already fixed at one endpoint. Although it is possible to extract logical code and include concerns modules, it is much more complicated than using the form object and basically putting the logic of one class into another violates a in the principles of OOP: single responsibility (S in SOLID). Putting all the logic into a separate class is easier to reuse, test, and maintain.

2. When to use form-object

More than one resource is affected

This is the most common case, by convention the controllers and models in rails are single resource-based. So, when business logic requires initializing or modifying, deleting many other resources, then we should gather these logic in one place for easy management, the best way is to use form object.

Combine validation for many resources

Usually we usually define the validation within the active-record models. eg:

But not only that, there are some models that are not active record can also have validation when initialized, assuming there is a Search class, we need to validate presence: true for the search_params property, but not an active record. model, so if done in the normal way, it must be implemented by itself, and the assignment of error messages to the search_params property is also limited, can only be displayed outside the interface as a flash message.

Validation is everywhere in our application, but how to handle validation for multiple models at the same time, if there are only a few validations that are only needed for some specific cases, put it inside the real model. It’s unnecessary and writing tests for these validations is sometimes difficult.

3. How to use the form object

Directory structure

The form object will be placed inside the app directory

And the class is named with the element _form

Create a class form

Create a class with required attributes

Class above compared to a normal ruby ​​class is usually no difference

Use ActiveModel :: Model.

Next, incluide module ActiveModel :: Model to be able to use methods found in the active model

Thus, we can now use the same validations methods as the active record model

Or can validate with validation that you define yourself

And now we can get the same error information as we do with the active record model, thanks to the valid method?

Customizing CRUD methods

The CRUD methods of the form object should follow the convention of the active record object, like save, update or create (or save !, update! Or create! When an exception is required) to be used similarly to an active record object.

And on the controller, we just need to implement the same active record object as follows

Use transaction

Since the form object is used to manage the influence of multiple resources, the use of transactions is essential to ensure data integrity when the data update of a resource fails.

Conclusion

Form Objects can help to mitigate a number of different problems when implementing Rails projects and therefore it can prove to be a useful tool for us, there is also a gem that can help. we can easily apply a form object to a project as reform

Source: https://nimblehq.co/blog/lets-play-design-patterns-form-objects

Share the news now

Source : Viblo