问题描述
我正在尝试制作一个简单的应用程序来提交用户目标,然后用户可以将目标标记为已完成。我可以很好地完成“新”操作,但是当我尝试“编辑”时,参数包括用户的ID而不是目标的ID。
对于部分表单,我使用一个简单的form_with:
> <%= form_with(model: [@user,@goal]) do |f| %>
> <%= f.label :goal_title,"Title" %>
> <%= f.text_field :goal_title %>
> <%= f.label :description,"Description" %>
> <%= f.text_area :description %>
> <%= f.select(:public,[['Public',true],['Private',false]]) %>
> <%= f.select(:completed,[['Completed',['Not Completed',false]]) %>
> <%= f.submit "Submit" %>
> <% end %>
我的控制器如下:
class GoalsController < ApplicationController
def index
@goals = current_user.goals
render :index
end
def new
@goal = Goal.new(user_id: current_user.id)
@user = current_user
render :new
end
def create
@goal = current_user.goals.new(goal_params)
if @goal.save
redirect_to user_goals_path
flash[:notice] = "Goal saved"
else
flash.Now[:errors] = @goal.errors.full_messages
render :new
end
end
def update
@goal = Goal.find_by(id: params[:id])
if @goal.update_attributes(goal_params)
redirect_to user_goals_path
flash[:notice] = "Goal updated"
else
flash.Now[:errors] = @goal.errors.full_messages
render :edit
end
end
def edit
@goal = Goal.find_by(id: params[:id])
@user = current_user
render :edit
end
def homepage
@goals = Goal.all
render :index
end
private
def goal_params
params.require(:goal).permit(:goal_title,:description,:completed,:public)
end
end
我当前的路线是:
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
user_goals GET /user/goals(.:format) goals#index
POST /user/goals(.:format) goals#create
new_user_goal GET /user/goals/new(.:format) goals#new
edit_user_goal GET /user/goals/:id/edit(.:format) goals#edit
user_goal PATCH /user/goals/:id(.:format) goals#update
PUT /user/goals/:id(.:format) goals#update
DELETE /user/goals/:id(.:format) goals#destroy
new_user GET /user/new(.:format) users#new
edit_user GET /user/edit(.:format) users#edit
user GET /user(.:format) users#show
PATCH /user(.:format) users#update
PUT /user(.:format) users#update
DELETE /user(.:format) users#destroy
POST /user(.:format) users#create
goals GET /goals(.:format) goals#homepage
root GET / goals#homepage
“编辑”中的params哈希显示正常:<ActionController::Parameters {"controller"=>"goals","action"=>"edit","id"=>"197"} permitted: false>
,但“更新”中的params显示<ActionController::Parameters {"_method"=>"patch","goal"=>{"goal_title"=>"Updated goal","description"=>"Updated description","public"=>"true","completed"=>"true"},"commit"=>"Submit","controller"=>"goals","action"=>"update","id"=>"379"} permitted: false>
。该ID应该是197(目标ID)而不是379(用户ID)。
有什么建议吗?谢谢。
解决方法
如果您再次查看路线,
user_goals GET /user/goals(.:format) goals#index
POST /user/goals(.:format) goals#create
new_user_goal GET /user/goals/new(.:format) goals#new
edit_user_goal GET /user/goals/:id/edit(.:format) goals#edit
user_goal PATCH /user/goals/:id(.:format) goals#update
PUT /user/goals/:id(.:format) goals#update
DELETE /user/goals/:id(.:format)
目标不是嵌套在用户资源中,而是用户在此处充当名称空间,因此,当您调用form_with(model: [@user,@goal])
时,Rails会选择user.id
作为id
的参数。
解决方案:
-
如果要使其成为嵌套资源,则需要将
config/routes.rb
中的路由配置更改为类似的内容。resources :users do resources :goals end
-
如果不需要嵌套资源,只需将
form_with(model: [@user,@goal])
更改为form_with(model: @goal)