Rails 5, не удалось найти пользователя без идентификатора and . Можете ли вы передать объект через форму?

#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 вспомогательного метода, а не через форму.