Are redirect_to and render exchangeable?

前端 未结 3 1215
梦如初夏
梦如初夏 2020-12-02 05:55

For the code below, what happens if replacing redirect_to with render or vise verse?

def create
  @product = Product.new(params[:product])

  respond_to do |         


        
3条回答
  •  猫巷女王i
    2020-12-02 06:57

    Here is a complete list of what the two methods do that I follow:

    1) redirect_to will issue an HTTP 302 status code by default. A 302 redirect is a temporary change and redirects users and search engines to the desired page for a limited amount of time until it is removed. You can optionally specifiy a 301 status code to redirect_to. A 301 status code is used when any page has been permanently moved to another location. Users will now see the new page as it has replaced the old page. This will change the URL of the page when it shows in search engine results.

    2) redirect_to will issue a new HTTP request, since it is redirects to a different controller action or URL. You should not make the browser need to make a fresh call unless you really have to, so always question when you are using redirect_to and if it is the right thing, or perhaps a render would be better. - redirect_to will cause any automatic template rendering of the current action to be skipped.

    3) render will issue an HTTP 200 status code by default ( but with an invalid ActiveRecord object, you may want to change this to 422 unprocessable entity). The HTTP 200 OK success status response code indicates that the request has succeeded. The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity nd the syntax of the request entity is correct but was unable to process the contained instructions.

    4) render will render a template and any instance variables defined in the controller action will be available in the template. Of course, instance variables will not be available if the subsequent action that redirect_to invokes. IMPORTANT POINT: Redirect hits the controller while Render does not, so if you render a different template, it will not hit the action associated with that template and so those instance variables will not be available!

    5) With render, use flash.now, instead of the normal flash.

    flash.now[:error] = "There was a problem"  
    # not 
    flash[:error] = "There was a problem"
    

    6) If you don't, then the flash message may not show up on the page that's rendered, and it will show up on the next page that's visited.

    7) render will not cause the current action to stop executing! redirect_to will not cause the current action to stop executing! You need to invoke 'return' if you need to bypass further execution of code in the action! In the below code, there is an explicit render at the bottom and so you must do a return to avoid an error of redirect and render both being present:

    def update
      @record = Record.new(record_params)
      if @record.save
        flash[:success] = "record was successfully saved"
        redirect_to records_path
        return
      end
      flash.now[:error] = "please fix the problems in the record"
      render :edit
    end
    

    Another option:

    def update
      @record = Record.new(record_params)
      if @record.save
        flash[:success] = "record was successfully saved"
        redirect_to records_path
      else
        flash.now[:error] = "please fix the problems in the record"
        render :edit
      end  
    end
    

    8) The flash message provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed to the very next action and then cleared out. This is a great way of doing notices and alerts:

    class PostsController < ActionController::Base
      def create
        # save post
        flash[:notice] = "Post successfully created"
        redirect_to @post
      end
    
      def show
        # doesn't need to assign the flash notice to the template, that's done automatically
      end
    end
    
    show.html.erb
      <% if flash[:notice] %>
        
    <%= flash[:notice] %>
    <% end %>

    Since you can have both notices and alerts in the flash, you can display both notices and alerts this way:

    <% flash.each do |key, value| %>
      <%= content_tag :div, value, class: "flash #{key}" %>
    <% end %>
    

提交回复
热议问题