collection_select в форме ROR передает значение в виде строки и не сохраняет - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь использовать collection_select (используя bootstrap_form_for) для сохранения связанной записи. Сохранение работает хорошо, используя консоль rails, поэтому я предполагаю, что определения моделей хороши (как и код контроллера).

Модель: Пользователь -

class User < ApplicationRecord
    validates :name, presence: true, length: {maximum: 50}
    validates :email, presence: true, length: {maximum: 250}, uniqueness: true

    has_secure_password
    validates :password, length: {minimum: 6}

    belongs_to :role
    has_many :issues_owned, :class_name => 'Issue', :foreign_key => 'owner'
    has_many :issues_assigned, :class_name => 'Issue', :foreign_key => 'assigned_to'    
end

Модель выпуска -

class Issue < ApplicationRecord
    belongs_to :assigned_to, :class_name => 'User'
    belongs_to :owner, :class_name => 'User'

    validates :summary, presence: true, length: {maximum: 100}
    validates :description, presence: true, length: {maximum: 250}
    validates :severity, presence: true, length: {maximum: 10}
    validates :priority, presence: true, length: {maximum: 10}

end

Код формы для добавления выпуска -

  <%= bootstrap_form_for(@issue, layout: :horizontal, label_col: "col-sm-2") do |form| %>

    <%= form.text_field :summary, control_col: 'col-md-4',class: 'input-sm' %>
    <%= form.text_area :description, control_col: 'col-md-8', class: 'input-sm' %>
    <%= form.text_field :severity, control_col: 'col-md-2', class: 'input-sm' %>
    <%= form.text_field :priority, control_col: 'col-md-2', class: 'input-sm' %>
    <%= form.collection_select :assigned_to,  @users, :id, :name, control_col: 'col-md-4' , class: 'input-sm' %>
    <%= form.date_field :resolved_at, control_col: 'col-md-4' , class: 'input-sm'%>
    <%= form.hidden_field :owner, control_col: ' col-md-4', value: @current_user %>
    <%= form.form_group do %>
      <%= form.primary "Create Issue", class:'btn btn-sm btn-primary' %>
    <% end %>

  <% end %>

Области интересов: assign_to - использование collection_select и: owner - который инициализируется с помощью @current_user.

В контроллере - код является стандартным на данный момент

  def create
    @issue = Issue.create(issue_params)

    respond_to do |format|
      if @issue.save!
        format.html { redirect_to @issue, notice: 'Issue was successfully created.' }
        format.json { render :show, status: :created, location: @issue }
      else
        format.html { render :new }
        format.json { render json: @issue.errors, status: :unprocessable_entity }
      end
    end
  end

... и

def issue_params
  params.require(:issue).permit(:summary,:description,:severity,:priority,:assigned_to, :owner,:resolved_at)
end

Как я упоминал ранее, этот код работает через консоль - добавляет запись о проблеме без каких-либо ошибок. Однако, когда я пытаюсь использовать его при отправке формы, я получаю следующую ошибку.

User(#70029712374140) expected, got "1" which is an instance of String(#47333497052640)

Я изучил документацию и другие подобные вопросы по SO, но не смог найти решение. Значение поля: owner передается правильно как объект пользователя, а поле: assign_to передается как строка. По какой-то причине магия рубина не работает для меня. Я уверен, что это что-то тривиальное, но я не могу придраться, так как пару дней и, следовательно, вопрос.

Любые указатели приветствуются.

ТИА.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Мне удалось сохранить запись после следующих изменений.

  1. измените значение параметра_параметров в контроллере, чтобы оно указывало на: assign_to_id и: owner_id
  2. изменить поля формы для Assigned To as: assign_to_id и Owner as: owner_id

Я просмотрел свои консольные скрипты и понял, что в моем рабочем примере также есть «_id» для полей. Я ошибся по поводу того, что он работает как есть.

Всегда думал, что это тривиально.

Спасибо @armont_development. Данное объяснение прояснило для меня немало указателей.

0 голосов
/ 20 января 2019

Я думаю, что ваша проблема, вероятно, связана с именами ваших внешних ключей в проблеме. Проблема принадлежит_области: owner и: assign_to, но в модели User внешними ключами также являются: owner и: assign_to - это заставляет меня поверить, что в вашей базе данных есть столбцы с именами: owner и: assign_to в таблице проблем

Способ связать, что объект Issue принадлежит_Пользователю, состоит в том, чтобы иметь Foreign_keys, которые являются идентификаторами, такими как: owner_id и: assign_to_id. Так что измените вашу таблицу проблем Foreign_keys с: object на: object_id и: assign_to на: assign_to_id. Формы не предназначены для передачи объектов в виде параметров, они должны передавать идентификаторы.

Ваша линия: <%= form.collection_select :assigned_to, @users, :id, :name, control_col: 'col-md-4' , class: 'input-sm' %> работает должным образом - он создает опции выбора для ключа: assign_to, где значения - это идентификаторы ваших пользователей, а метки - это имена. Как уже упоминалось, я бы изменил вашу базу данных, чтобы иметь: assign_to_id для вашего объекта Issue, а затем обновил бы эту строку до:

<%= form.collection_select :assigned_to_id, @users, :id, :name, control_col: 'col-md-4' , class: 'input-sm' %>

В таком случае вы также указали бы: owner_id в вашем объекте Issue, поэтому ваше поле hidden_id должно измениться на:

<%= form.hidden_field :owner_id, control_col: ' col-md-4', value: @current_user.id %>

(обратите внимание, что если есть вероятность, что @current_user может быть равен нулю, замените @current_user.id на @current_user.try(:id))

Вам потребуется обновить ваши strong_params в контроллере до:

def issue_params
  params.require(:issue).permit(:summary,:description,:severity,:priority,:assigned_to_id, :owner_id,:resolved_at)
end

И, наконец, если вы измените эти столбцы на: owner_id и: assign_to_id, то вам нужно обновить модель пользователя, чтобы иметь следующие отношения:

    has_many :issues_owned, :class_name => 'Issue', :foreign_key => 'owner_id'
    has_many :issues_assigned, :class_name => 'Issue', :foreign_key => 'assigned_to_id'    
...