1

I think I don't understand routes in rails. I would like to hide navbar and footer when user is on checkout page.

So far I tried to do something like this:

  <body>
  <% if current_page?(new_checkout_path)  %>
    <%= yield %>
  <% else %>
    <%= render 'layouts/navbar' %>
    <%= yield %>
    <%= render 'layouts/footer' %>
  <% end %>
  </body>

and that is working. There is no navbar or footer.

My problem is when user try to submit form and validation do not want to accept that.

If I understand that correctly: Controller tries to save/create which is "post" method, but can't, so it push to do :new once again...and now I don't understand.

We are on checkouts_path but that it is actually checkouts with method: :post not :get one. That's why we don't render index page.

Why we aren't once again on new_checkout_path? Because our form wasn't saved at all? How to pass to my poor if statment something like:

<% if current_page?(new_checkout_path) || current_page?(checkouts_path, method: :post %>

Is there any way to do that this way? I had read Rails Routing from the Outside In and tried to override default routes but ended with nothing. Is there anyone patient to help me with understanding that?

Thank you.

artdeb444
  • 11
  • 3
  • Does this answer your question? [Rails current\_page? "fails" when method is POST](https://stackoverflow.com/questions/9749807/rails-current-page-fails-when-method-is-post) – Eyeslandic Apr 22 '20 at 12:22

1 Answers1

0

The difference between the new and create routes is a common source of confusion for beginners and is all down to impotency and how REST uses the HTTP methods to properly distinguish between different actions.

# Given
rails g scaffold article title:string body:text

This gives us a GET /articles/new route which just displays the form. This is an idempotent route as it will display the same results to any visitor. When we actually post the form it is sent as POST /articles which is a non-idempotent action as it creates a resource.

class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]

  # ...

  # POST /articles
  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to @article, notice: 'Article was successfully created.'
    else
      render :new
    end
  end

  # ...

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_article
      @article = Article.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def article_params
      params.require(:article).permit(:title, :body)
    end
end

What you and everybody else get hung up on is render :new. This line does not redirect. It just renders /app/views/articles/new.html.erb and sends it in the response. The path in the browser is /articles as that's where the form submits to. What you are seeing is the result of performing a non-idempotent action.

If you want to check if you are in the new or create action of a specific controller you want to use controller_name and action_name instead:

<% if controller_name == "checkouts" && ["new", "create"].include?(action_name) %>
  # ...
<% end %>
max
  • 96,212
  • 14
  • 104
  • 165