#ruby-on-rails #ruby #controller #devise #nested
#ruby-on-rails #ruby #контроллер #разработать #вложенный
Вопрос:
Я пытаюсь создать простое приложение для отправки целей пользователей, которые затем могут пометить цели как завершенные. Я могу выполнить «новое» действие нормально, но когда я пытаюсь «редактировать», параметры включают идентификатор пользователя вместо идентификатора цели.
Для моей формы partial я использую простую 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', true], ['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
Хэш параметров в «редактировать» отображается нормально: <ActionController::Parameters {"controller"=>"goals", "action"=>"edit", "id"=>"197"} permitted: false>
но отображаются параметры для «обновить» <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>
. Идентификатор должен быть 197 (идентификатор цели), а не 379 (идентификатор пользователя).
Есть предложения? Спасибо.
Комментарии:
1. нет необходимости писать user в form_with, просто напишите form_with(модель: @goal), и это решит вашу проблему. Кроме того, вы можете написать маршруты участников, чтобы вам не приходилось писать goal = Goal.find_by(id: params[:id]) в методах редактирования и обновления.
Ответ №1:
Если вы снова посмотрите на свои маршруты:
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)
Комментарии:
1. Я смог сохранить свой уникальный пользовательский ресурс и изменил свой form_with на:
<% action_url = @goal.persisted? ? user_goal_path(@goal) : user_goals_path %> <%= form_with(model: @goal, url: "#{action_url}") do |f| %>
2. Отлично, если это соответствует вашим потребностям.