user3711600
user3711600

Reputation: 873

link_to method not routing to a PATCH request when I include a query string parameter

I'm trying to create a cancel button in a rails view, which links to a PATCH/update method. I want to pass a query string parameter -- update_action: "cancel" -- so the update method knows that this is a cancel action and can process it accordingly. This is the link_to method for the cancel button:

<%= link_to "Cancel", {controller: "/orders", action: "update", id: order.id, update_action: "cancel" }, method: "patch" %>

However, when I do this, I get a routing error:

Unable to find route for [GET] order/update/id?update_action=cancel

For some reason it is trying to route to a GET request instead of a PATCH request.

Now, when I remove the query string parameter from the link_to method, i.e.

<%= link_to "Cancel", {controller: "/orders", action: "update", id: order.id }, method: "patch" %>

It correctly routes to PATCH orders/id,

Why is my link_to method not routing to a PATCH request when I include the query string parameter?

Note, by routes.rb file contains:

resources :orders

Upvotes: 3

Views: 2734

Answers (1)

Shifa Khan
Shifa Khan

Reputation: 779

You can give this a try, though I doubt it will work any better:

<%= link_to "Cancel", order_path(id: order.id, update_action: "cancel"), method: "patch" %>

Routing in rails is implemented using RESTful architecture. Hence you can send query string params with a GET request. A PUT request typically does not contain query params. Those params are submitted in the request body (like using a form) as seen in the example below from guides

class ClientsController < ApplicationController
  # This action uses query string parameters because it gets run
  # by an HTTP GET request, but this does not make any difference
  # to the way in which the parameters are accessed. The URL for
  # this action would look like this in order to list activated
  # clients: /clients?status=activated
  def index
    if params[:status] == "activated"
      @clients = Client.activated
    else
      @clients = Client.inactivated
    end
  end

  # This action uses POST parameters. They are most likely coming
  # from an HTML form which the user has submitted. The URL for
  # this RESTful request will be "/clients", and the data will be
  # sent as part of the request body.
  def create
    @client = Client.new(params[:client])
    if @client.save
      redirect_to @client
    else
      # This line overrides the default rendering behavior, which
      # would have been to render the "create" view.
      render "new"
    end
  end
end

If you only want a 'Cancel' button, you can use the same path as a GET request. Your params {update_action:"cancel"} will be available in the controller. It also makes sense as you are trying to GET/fetch a different page.

A PUT/PATCH request is used to update/create data in models, while POST is to create. A GET request will fetch pages, or back to previous pages (like in cases of 'cancel').

Upvotes: 1

Related Questions