Bret
Bret

Reputation: 1475

Resource defines an update using PATCH but app wants POST in Rails 4

I'm trying to add edit functionality to my web app, and am having some trouble. The error page I get back when I try to complete an edit of my Request object indicates that it couldn't find the right route, but the same error page contains a list of routes which includes the route it's looking for. So I'm a bit flummoxed.

The "new" method is almost identical to this edit method and the pages are almost identical as well.

The error page begins No route matches [POST] "/requests/19/edit" and then, partway down the route listing, I see this:

requests_path   GET /requests(.:format) requests#index
POST    /requests(.:format) requests#create
new_request_path    GET /requests/new(.:format) requests#new
edit_request_path   GET /requests/:id/edit(.:format)    requests#edit
request_path    GET /requests/:id(.:format) requests#show
PATCH   /requests/:id(.:format) requests#update
PUT /requests/:id(.:format) requests#update
DELETE  /requests/:id(.:format) requests#destroy

So Rails seems to be generating a request_path which expects a PATCH, not a POST, right?

routes.rb

Rails.application.routes.draw do    
  root "pages#index"    
  resources :destinations    
  resources :users
  resources :manifests    
  resources :requests 
  :

request.rb

class Request < ActiveRecord::Base    
  validates_presence_of :justification
  validates_presence_of :required_by    
  belongs_to :user
  belongs_to :manifest
  belongs_to :network
  has_many :uploaded_files    
  scope :sorted, lambda{ order("required_by") }    
end

edit.html.rb

<% @page_title = "Update Request" %>
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="requests edit">
  <h2>Update Request</h2>
  <%= form_for :request, url: request_path(@request) do |f| %>
    <%= render(:partial => "form", :locals => {:f => f}) %> 
    <div class="form-buttons">
      <%= submit_tag("Update Request") %>
    </div>
  <% end %>
</div>

requests_controller.rb

  def update
    @request = Request.find(params[:id])
    p = {'file' => params[:request][:uploaded_file], 'request_id' => @request.id}
    uf = UploadedFile.create(p)
    if @request.update_attributes(request_params)
      flash[:notice] = "Request updatred succesfully"
      redirect_to :action => 'show', :id => @request.id
    else
      render 'edit'
    end
  end

What have I missed?

Upvotes: 0

Views: 92

Answers (1)

Pavan
Pavan

Reputation: 33542

Change

<%= form_for :request, url: request_path(@request) do |f| %>

to

<%= form_for :request, url: request_path(@request), method: :patch do |f| %>

in your edit.html.erb

form_for(as you are using it) sets POST as default HTTP verb. You need to alter it by setting method :patch which responds to the update action.

You can simplify it to just

<%= form_for @request do |f| %>

Check the APIdoc for more Info.

Upvotes: 1

Related Questions