尝试编辑时,Rails form_for 导致 POST 而不是 PUT [英] Rails form_for results in POST instead of PUT when trying to edit

查看:48
本文介绍了尝试编辑时,Rails form_for 导致 POST 而不是 PUT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Rails 4 并出现以下错误.

<块引用>

路由错误
没有路由匹配 [POST] "/logs/1/meals/13/edit

我正在使用 :meal 传递 form_for 模型对象,并且编辑页面正在正确呈现.但是,Rails 似乎并没有检查是否已经保存了膳食对象,因此它一直尝试将表单发送到 #create 操作并尝试发出 POST 请求,而不是将表单发送到更新操作并进行当我点击提交时的 PUT 请求.

如何让 form_for 识别出我正在尝试更新现有对象并且需要 PUT 而不是 POST?其他一切正常,我已经运行了所有迁移.我对 Rails 还很陌生,我几乎花了一整天的时间试图自己解决这个问题.请帮忙!

请注意,当我尝试将模型对象作为 @meal.log 而不是 :meal 传入时,Rails 不再能够识别 :calorie_estimate 或 :meal_description.将模型对象作为 @meal.log 传递给我留下了无方法错误.

膳食/edit.html.erb

编辑膳食 </h3><%= form_for(:meal) do |f|%><div id="meal-form"><%= f.text_field :calorie_estimate, class: 'meal-form-fields', :placeholder =>卡路里估计"%><%= f.text_field :meal_description, class: 'meal-form-fields', :placeholder =>食物说明"%><div class="submit-form" style="width: 75px; height: 15px;"><%= f.submit 'UPDATE', :class =>'提交表单文本'%>

<%结束%>

meals_controller.rb

class MealsController <应用控制器包括 MealsHelper定义创建@meal = Meal.new(meal_params)@meal.log_id = params[:log_id]@meal.saveredirect_to log_path(@meal.log)结尾定义编辑@meal = Meal.find(params[:id])结尾定义更新@meal = Meal.find(params[:id])@meal.update(meal_params)重定向到日志路径(@log)结尾定义膳食参数params.require(:meal).permit(:calorie_estimate, :meal_description)结尾结尾

可能的路线:

前缀动词URI模式控制器#Action根获取/日志#indexlog_meals GET/logs/:log_id/meals(.:format) 膳食#indexPOST/logs/:log_id/meals(.:format) 饭食#createnew_log_meal GET/logs/:log_id/meals/new(.:format) 餐#newedit_log_meal GET/logs/:log_id/meals/:id/edit(.:format) 膳食#editlog_meal GET/logs/:log_id/meals/:id(.:format) 餐#showPATCH/logs/:log_id/meals/:id(.:format) 餐#updatePUT/logs/:log_id/meals/:id(.:format) 餐#update删除/logs/:log_id/meals/:id(.:format) 餐#destroy日志 GET/logs(.:format) 日志#indexPOST/logs(.:format) 日志#createnew_log GET/logs/new(.:format) 日志#newedit_log GET/logs/:id/edit(.:format) 日志#editlog GET/logs/:id(.:format) 日志#showPATCH/logs/:id(.:format) 日志#updatePUT/logs/:id(.:format) 日志#update删除/logs/:id(.:format) 日志#destroy

routes.rb

Rails.application.routes.draw 做根到:'日志#index'资源:日志做资源:膳食结尾结尾

schema.rb

ActiveRecord::Schema.define(version: 20160128205351) do# 这些是必须启用才能支持此数据库的扩展enable_extension "plpgsql"create_table "logs", force: :cascade do |t|t.string "entry_date"t.integer "calorie_goal"t.string "笔记"t.datetime "created_at"t.datetime "updated_at"结尾create_table "meals", force: :cascade do |t|t.integer "calorie_estimate"t.string "meal_description"t.整数log_id"t.datetime "created_at"t.datetime "updated_at"结尾结尾

解决方案

问题在于您正在使用 嵌套资源,因此您对将哪些 @objects 传递给您的 form_for 感到困惑.

#app/views/meals/edit.html.erb<%= form_for [@log, @meal] do |f|%>

<小时>

正如您目前所拥有的,传递 :meal 是模棱两可的 - Rails 无法辨别要将其提交的路由/方法,因为它没有该数据可用.

如果您想更新一个对象,您必须将适当的数据传递给表单,包括对象的id:

<%= form_for :meal, url: { controller: "meals", action: "update", id: "5" }, method: :put do |f|%>

比如 Rails 是面向对象,你最好传递实际的对象到您的 form_for:

<%= form_for @meal ...

--

您遇到的问题是您有一个嵌套资源:

resources :logs 做资源:膳食#->url.com/logs/:log_id/meals/:id结尾

这意味着你需要通过LogMeal 值到您的 form 中:

#app/controllers/meals_controller.rb类 MealsController <应用控制器定义编辑@log = Log.find params[:log_id]@meal = Meal.find params[:id]结尾定义更新@log = Log.find params[:log_id]@meal = Meal.find params[:id]@meal.update meal_params结尾结尾#app/views/meals/edit.html.erb<%= form_for [@log, @meal] do |f|%>

I am using Rails 4 and have the following error.

Routing Error
No route matches [POST] "/logs/1/meals/13/edit

I’m passing form_for the model object using :meal and the edit page is rendering correctly. However, Rails does not seem to be checking whether or not the meal object has already been saved, so it keeps trying to send the form to the #create action and tries make a POST request instead of sending the form to the update action and making a PUT request when I hit submit.

How do I get the form_for to recognize that I am trying to update an existing object and that PUT is needed instead of POST? Everything else is working and I’ve run all of my migrations. I’m pretty new to Rails, and I’ve spent almost all day trying to figure this out on my own. Please help!

And just to note, when I tried to pass in the model object as @meal.log instead of :meal, Rails was no longer able to recognize :calorie_estimate or :meal_description. Passing the model object as @meal.log left me with a no method error.

meals/edit.html.erb

<h3> EDIT MEAL </h3>
<%= form_for(:meal) do |f| %>
<div id="meal-form">
    <%= f.text_field :calorie_estimate, class: 'meal-form-fields', :placeholder => "Calorie Estimate" %>
    <%= f.text_field :meal_description, class: 'meal-form-fields', :placeholder => "Food Description" %>
  <div class="submit-form" style="width: 75px; height: 15px;">
    <%= f.submit 'UPDATE', :class => 'submit-form-text' %>
  </div>
</div>
<% end %>

meals_controller.rb

class MealsController < ApplicationController
  include MealsHelper

  def create
    @meal = Meal.new(meal_params)
    @meal.log_id = params[:log_id]
    @meal.save

    redirect_to log_path(@meal.log)
  end

  def edit
    @meal = Meal.find(params[:id])
  end

  def update
    @meal = Meal.find(params[:id])
    @meal.update(meal_params)
    redirect_to log_path(@log)
  end

  def meal_params
    params.require(:meal).permit(:calorie_estimate, :meal_description)
  end

end

possible routes:

Prefix Verb   URI Pattern                            Controller#Action
         root GET    /                                      logs#index
    log_meals GET    /logs/:log_id/meals(.:format)          meals#index
              POST   /logs/:log_id/meals(.:format)          meals#create
 new_log_meal GET    /logs/:log_id/meals/new(.:format)      meals#new
edit_log_meal GET    /logs/:log_id/meals/:id/edit(.:format) meals#edit
     log_meal GET    /logs/:log_id/meals/:id(.:format)      meals#show
              PATCH  /logs/:log_id/meals/:id(.:format)      meals#update
              PUT    /logs/:log_id/meals/:id(.:format)      meals#update
              DELETE /logs/:log_id/meals/:id(.:format)      meals#destroy
         logs GET    /logs(.:format)                        logs#index
              POST   /logs(.:format)                        logs#create
      new_log GET    /logs/new(.:format)                    logs#new
     edit_log GET    /logs/:id/edit(.:format)               logs#edit
          log GET    /logs/:id(.:format)                    logs#show
              PATCH  /logs/:id(.:format)                    logs#update
              PUT    /logs/:id(.:format)                    logs#update
              DELETE /logs/:id(.:format)                    logs#destroy

routes.rb

Rails.application.routes.draw do

  root to: 'logs#index'

  resources :logs do
    resources :meals
  end
end

schema.rb

ActiveRecord::Schema.define(version: 20160128205351) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "logs", force: :cascade do |t|
    t.string   "entry_date"
    t.integer  "calorie_goal"
    t.string   "notes"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "meals", force: :cascade do |t|
    t.integer  "calorie_estimate"
    t.string   "meal_description"
    t.integer  "log_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

解决方案

The issue is that you're using nested resources, hence you're confused about which @objects to pass to your form_for.

#app/views/meals/edit.html.erb
<%= form_for [@log, @meal] do |f| %>


As you have it presently, passing :meal is ambiguous - Rails cannot discern the route / method to send its submission to, as it doesn't have that data available.

If you wanted to update an object, you'll have to pass the appropriate data to the form, including the object's id:

<%= form_for :meal, url: { controller: "meals", action: "update", id: "5" }, method: :put do |f| %>

Such as Rails is object orientated, you'll be best passing the actual object to your form_for:

<%= form_for @meal ...

--

The issue you have is that you have a nested resource:

resources :logs do
  resources :meals #-> url.com/logs/:log_id/meals/:id
end

This means you need to pass both the Log and Meal values to your form:

#app/controllers/meals_controller.rb
class MealsController < ApplicationController
  def edit
     @log  = Log.find params[:log_id]
     @meal = Meal.find params[:id]
  end

  def update
     @log  = Log.find params[:log_id]
     @meal = Meal.find params[:id]   
     @meal.update meal_params     
  end
end

#app/views/meals/edit.html.erb
<%= form_for [@log, @meal] do |f| %>

这篇关于尝试编辑时,Rails form_for 导致 POST 而不是 PUT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆