Want to edit/PUT/PATCH but error says "No route matches [POST]"

时间:2015-12-08 19:27:54

标签: ruby-on-rails ruby

I'm building my second-ever basic Ruby on Rails application and having fun doing it, but have gotten stuck at precisely the same place that gave me trouble (and was never solved) on my last effort: the PUT or PATCH request.

My application has two models: entries and users. A logged-in user should be able to edit only those entries that were originally created by that user.

CONTROLLER

[
    ['', '700', '-', '-', '-', '5,179.00', '-', '1,350', '4,972.25', '5,006.15', '450', '2700.00', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', ''], 
    ['', '-', '-', '-', '-', '-', '-', '1,200', '4,710.85', '5,254.15', '150', '2800.00', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', ''],
    ...
]

VIEW (show.html.erb - shows a single entry and includes links allowing the logged-in user who originally authored the entry to edit or delete it)

class EntriesController < ApplicationController
# authenticate user (Devise)
before_action :authenticate_user!, :except => [:index, :show]
# set entry upon page load
before_action :set_entry, :only => [:show, :edit, :update, :destroy]

# GET request - display all entries
def index
    @all_entries = Entry.all
end

# GET request - display an individual entry
def show
    # nothing required here because entry identified with before_action :set_entry on line 2 above
end

# GET request - access form to create a new entry
def new
    @entry = Entry.new
    @user = User.find(current_user[:id])
end

# GET request - access form to update an existing entry
def edit
    if @entry[:user_id] != current_user[:id]
        redirect_to root_path
    else 
        redirect_to edit_entry_path
    end
end

# POST request - make a new entry/save new data into db
def create
    user = current_user[:id]
    Entry.create({
        entry_title: params[:entry][:entry_title], 
        book_title: params[:entry][:book_title],
        text: params[:entry][:text], 
        img_url: params[:entry][:img_url], 
        tag: params[:entry][:tag], 
        created_at: params[:entry][:created_at], 
        user_id: user 
    })
    redirect_to entries_path
end

# PUT request - save changes to an existing entry
def update
    if @entry.update(entry_params)
        redirect_to entry_path
    else 
        render :new
    end
end

# DELETE request - delete an existing entry from db
def destroy
    @entry.destroy
    redirect_to entries_path
end

private

def set_entry
    @entry = Entry.find(params[:id])
end

def entry_params
    params.require(:entry).permit(:email, :text, :tag)
end

end

ROUTES.RB - At first my routes were the commented-out lines, but then I had a thought that was either madness or sudden realization - should only the GET routes lead with "get"? So that's the non-commented-out attempt you see. Somehow the app works (except for the issue at hand) both ways.

In researching I've come across routes defined using a much more elaborate syntax than that I'm using here. I've been unable to figure out whether a given way of doing things is different convention, outdated, or just inadequate to the task.

<h3>Selected Entry</h3>
    <div class="row">
        <div class="col-md-2"></div>
        <div class="col-md-6">
            <div>Entry title: <%= @entry.entry_title %></div>
            <div>Book title: <%= @entry.book_title %></div>
            <div>Text: <%= @entry.text %></div>
        </div>
        <div class="col-md-4">
            <div><%= @entry.created_at.strftime("%b %d, %Y") %></div>
            <div>Submitted by: <i><%= @entry.user.email %></i></div>
            <div>File under: <i><%= @entry.tag %></i></div>

            <% if current_user %>
                <%= link_to 'Edit', @entry, :method => 'update' %>
                <%= link_to 'Delete', @entry, :method => 'delete' %>
            <% end %>
        </div>
    </div>

Thanks in advance for any insight. If additional context is needed I'm happy to provide.

Edited to add: PARTIAL (_form.html.erb)

Rails.application.routes.draw do
  devise_for :users
  resources :entries

  # root 'entries#index'

  # get '/entries' => 'entries#index'

  # get '/users' => 'users#index'

  # get '/entries/:id' => 'entries#show'

  # get '/entries/:id' => 'entries#update'

  # get '/entries/new' => 'entries#new'

  # get '/entries/:id/edit' => 'entries#edit'

  # get '/users/:id' => 'users#show'

  # get '/about' => 'pages#index'

  root 'entries#index'

  get '/entries' => 'entries#index'

  get '/entries/new' => 'entries#new'

  post '/entries' => 'entries#create'

  get '/entries/:id' => 'entries#show'

  get '/entries/:id/edit' => 'entries#edit'

  put '/entries/:id' => 'entries#update'

  delete '/entries/:id' => 'entries#destroy'

  get '/users' => 'users#index'

  get '/users/:id' => 'users#show'

  get '/about' => 'pages#index'

end

4 个答案:

答案 0 :(得分:0)

:method助手中的

link_to是指HTML动词(获取,发布等),而命名约定的控制器方法是动作。

link_to

你需要一些东西

<%= link_to 'Edit', @entry, :method => 'put' %>

<%= link_to 'Edit', @entry, :action => 'update' %>

答案 1 :(得分:0)

您一眼就试着发布编辑链接。记住new / edit是get方法来呈现表单,所以只需删除链接中的方法部分即可。喜欢来自

<%= link_to 'Edit', @entry, :method => 'update' %>

<%= link_to 'Edit', edit_entry_path(@entry) %>

答案 2 :(得分:0)

编辑你的记录

  • 首先,应该使用GET请求来获取编辑表单
  • 第二,应使用PUT / PATCH请求提交该表单

要进入编辑表单,您应该链接到条目的编辑路径

<%= link_to 'Edit', edit_entry_path(@entry) %>

Rails表单助手会自动将表单设置为使用正确的方法PUT或PATCH提交。

答案 3 :(得分:0)

  

我正在构建我的第二个基本的Ruby on Rails应用程序

恭喜!在一切开始有意义之前,你至少还需要3个

要添加到现有答案中,您最好先查看resources directive来清理路线:

#config/routes.rb
root 'entries#index'
devise_for :users

resources  :entries
resources  :pages,  only: [:index], path_names: { index: "about" }
resources  :users,  only: [:index,:show]

-

  

登录用户应该只能编辑那些最初由该用户创建的条目

这称为授权

  • 身份验证 =用户已登录?
  • 授权 =用户可以这样做吗?

虽然人们会混淆Devise能够处理授权,但它只处理身份验证。虽然您在控制器中有一个简单的实现,但您应该查看CanCanCanPundit宝石:

#Gemfile
gem "cancancan"

#app/models/ability.rb
class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)
    can :manage, Post, user_id: user.id
  end
end

#app/controllers/entries_controller.rb
class EntriesController < ApplicationController
   def edit
      authorize! :edit, @entry
   end
end

-

最后,要直接回答您的问题,您需要调用update方法(不存在)来访问编辑视图:

<% if current_user %>
   <%= link_to 'Edit', @entry, :method => 'update' %>
   <%= link_to 'Delete', @entry, :method => 'delete' %>
<% end %>

你应该阅读http verbs - 这就是&#34;方法&#34;选项使用link调用。如上所述,您在使用edit时不需要设置GET的方法。 Update使用put/patch,我稍后会解释。

实现目标的更好方法如下:

<%= link_to "Edit", edit_entry_path(@entry) if can? :edit, @entry %>
<%= link_to "Delete", @entry, method: :delete, if can? :destroy, @entry %>

以上使用CanCanCan授权方法can?