#ruby-on-rails #ruby #forms #action
#ruby-on-rails #ruby #формы #Экшен
Вопрос:
Я пытаюсь закодировать возможность для пользователя добавлять навык (принадлежит пользователю, технологии и уровню) в свой набор навыков.
У меня есть simple_for_for в skills/ new.html.erb:
<%= simple_form_for [ @user, @skill ] do |f| %>
<p>Select Tech</p>
<div>
<%= f.collection_select :technology_id, @techs, :id, :name%>
</div>
<p>Select Level</p>
<div>
<%= f.collection_select :level_id, @levels, :id, :name%>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
Контроллер навыков: новым действием является передача списка объектов технологий и уровней в simple_form_for, поэтому параметры, которые пользователь может выбрать, представляют собой список всех технологий и уровней (скажем, Tech: Ruby, Level: Junior).
class SkillsController < ApplicationController
before_action :authenticate_user!
def index
@skills = policy_scope(Skill)
end
def new
@techs = Technology.all
@levels = Level.all
@skill = Skill.new
@user = current_user
authorize @skill
end
def create
skill = Skill.new(skill_params)
authorize skill
if skill.save
redirect_to projects_path
else
render :action => "new", @user => params[:user_id], @skill => skill
end
end
private
def skill_params
params.require(:skill).permit(:user_id, :technology_id, :level_id)
end
end
У меня возникла пара проблем:
Предложение else неправильно отправляет @user и @skill в форму после того, как не удается сохранить новый навык, но я не знаю, правильный ли синтаксис.
Актуальная проблема: нормально ли, чтобы форма передавала технологию и идентификатор уровня, связанные с выбранной опцией, а не с самим объектом? Я попытался вручную найти все компоненты навыков вручную, как это, что выдает ошибку «Не удалось найти пользователя без идентификатора и»:
def create
skill = Skill.new()
technology = Technology.find(skill_params[:technology_id])
level = Level.find(skill_params[:level_id])
user = User.find(skill_params[:user_id])
skill.user = user
skill.technology = technology
skill.level = level
authorize skill
if skill.save
redirect_to projects_path
else
render :action => "new", @user => user, @skill => skill
end
end
private
def skill_params
params.require(:skill).permit(:technology_id, :level_id, :user_id)
end
Комментарии:
1. Пожалуйста, добавьте журналы запросов — Для проверки параметров запроса
Ответ №1:
Сначала убедитесь, что вы настроили связь между пользователем и навыками, на основе которых вы можете создавать новые записи:
class User
has_many :skills
end
Если ваше приложение просто позволяет пользователям добавлять навыки в свою учетную запись, вам следует просто извлечь текущего пользователя из сеанса:
def create
@skill = current_user.skills.new(skill_params)
authorize @skill
if @skill.save
redirect_to projects_path
else
render :new
end
end
Обратите внимание, что это полностью устраняет необходимость вложенности формы и маршрута:
resources :skills
<%= simple_form_for @skill do |f| %>
# ...
<% end %>
Ответ №2:
В вашем действии создания вы можете установить @user
и @skill
, прежде чем пытаться создать / сохранить его, а затем вы можете просто отобразить new в предложении else:
def create
@user = current_user
@skill = Skill.new(skill_params)
authorize @skill
if @skill.save
redirect_to projects_path
else
render :new
end
end
И да, вы можете передать идентификатор, потому что идентификатор — это то, что будет сохранено в базе данных.
Причина ошибки Не удалось найти пользователя без идентификатора, вероятно, потому, что у skill_params нет идентификатора пользователя. Идентификатор пользователя вы получаете с помощью current_user
вспомогательного метода, а не через форму.