This post explains my recent experience regarding the endevour of implementing shared custom response from multiple controller actions in Ruby On Rails.
Lets say we have a controller. Inside it lies the following actions: action_1, action_2, action_3 and action_4. All of these actions would respond with custom response and for convenience the responses will be in JSON format. We need to send the same custom response from different actions, thus the response needs to be shared.
Such scenarios my arise when:
- We need to validate some data before proceeding further.
- The logic of the controller depends on the value of supplied params. If params is not present, controller needs to respond with respective message. etc…
The following text explains all the approaches which I tried for implementation of such requirements. And why one is better that the other.
Attempt 1
This approach uses a shared method to perform extra logic and provide a Boolean response which determines the action’s response. The logic is performed in res_n method and the response is returned from controller action.
As we can see, it has a lot of code duplication. The success response may be different but the error response need to be repeated in all actions. It violated the ruby’d DRY principle.
Attempt 2
This approach minimizes the code redundancy by moving the common error response to res_n methods. As you may have noticed the built-in method performed? is used. This method returns true if render method has already been invoked earlier. This way we prevent render method being called multiple times. The code is more simpler and cleaner than the first approach.
Attempt 3
This approach is the best among the previous two approaches. With a lot of research on code refactoring on this scenario I stumbled on this solution. It automatically prevents render method being called multiple times and make code more shorter, cleaner and easier than the 2nd approach. It uses built-in controller method before_action
. This method gets called before each time a controller’s action is executed. The control of the program never enter the action method if it is returned from before_action method.
Conclusion
In this post, I have tried to explain the problem I faced during my ROR internship. And how I manged to solve it, trying different approaches, improving each time. Although the last attempt seems to be the best one, there may be scenarios where we need to implement the techniques of former approaches too.