尝试编辑时,Rails form_for 导致 POST 而不是 PUT [英] Rails form_for results in POST instead of PUT when trying to edit
问题描述
我正在使用 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结尾
这意味着你需要通过Log
和 Meal
值到您的 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屋!