Performing another controller action in Ruby on Rails

This happened to me several times, and I have not yet found an acceptable solution.

I have a form on the website’s home page that forms the points to another controller who actually does the data processing work. When the form submits successfully, another controller sends you back to the home page with a nice flash [: notice] message and finishes it.

When a verification problem occurs, it becomes a problem. I would like to show the home page with a form with validation errors. The naive solution, as a rule, mentions that you can display another template, but show the home page much more than the visualization of the template, it has a lot of functionality. The only way to visualize this template is to copy and paste the functionality into this other controller action or, possibly, remove all the functionality from the controller, which is not very nice.

Is there a better solution?

Update . I understand that people say that the actions of the controller should be less and call a different method, but in practice I do not see how to achieve it. I am going to post a real example from a website that I made.

There are two models and controllers: posts and comments. The message has many reasons. The message is shown as follows:

def index set_posts # sets @posts end def show @post = Post.find_by_slug(params[:id]) @comment = Comment.new if not @post flash[:error] = "'#{params[:id]}' does't exist" set_posts render :action => :index, :status => :not_found end end private def set_posts @posts = Posts.get_all_public_posts end 

The comment controller only has a create action:

 def create @comment = Comment.new(params[:comment]) @comment.post = Post.find_by_slug params['post_id'] if not @comment.post # Now what? # We should here call PostsController.set_posts and render views/posts/index end if @reason.save flash[:notice] = 'Thank you for your message.' redirect_to(@reason.item) else # Now what? # We should here call PostsController.show without overriding the @comment end end 

end

"What now?" parts for which I do not have a good solution.

+4
source share
4 answers

How much of the rest of the homepage changes between when the form is displayed and the request is redirected to the default action?

If there isn’t so many answers, you should consider using remote_form_for and update only the success notification area or form with a validation error on failure.

If you don’t like it, you can transfer all the repeating logic to the action of the home page on the method defined in the ApplicationController class and call it as part of the before_filter in the main page action and the action that processes your form. NB : for this you need to set the instance variables, the local variables set in the filter will not be saved until the action.

+1
source

I have encountered this problem before. I came from CakePHP, where validation errors are stored in a session and persist between requests. Rails does not behave by default, leaving you with a decision on how to handle errors.

As you apparently also read, putting errors into the session and doing redirection is generally not recommended in the Rails world. And, as you say, the Rails path seems to just perform another action without doing the redirection. When I first tried to do this, I noticed that I had to duplicate a lot of code in order to configure the second action to display the first action.

As with any type of code duplication, the solution is to move the duplicated code into a separate method, and then call this method in two steps. A clean way to do this is to use before_filter to run the code for both actions.

+1
source

How is this different from regular vanilla rails?

 if(valid) flash = ... redirect_to :home else rerender form with error messages & submitted values end 
0
source

I agree with the other posters here - if you have a similar code, it just translates into a common method called each of the controller actions.

Application Controller is the best place to host it if it is distributed across multiple controllers.

Alternatively, you can create a general controller class that inherits both controllers and that contains only this helper method. I do not recommend this unless you are likely to share other methods.

0
source

Source: https://habr.com/ru/post/1302318/


All Articles