Ошибка проверки. Класс должен существовать.

У меня была (часовая) проблема с ассоциациями в Rails. Я нашел много подобных проблем, но я не мог подать заявку на мой случай:

Класс города:

class City < ApplicationRecord
  has_many :users
end

Класс пользователя:

class User < ApplicationRecord
  belongs_to :city

  validates :name, presence: true, length: { maximum: 80 }
  validates :city_id, presence: true
end

Пользовательский контроллер:

def create
    Rails.logger.debug user_params.inspect
    @user = User.new(user_params)
    if @user.save!
      flash[:success] = "Works!"
      redirect_to '/index'
    else
      render 'new'
    end
 end

def user_params
  params.require(:user).permit(:name, :citys_id)
end

Просмотр пользователей:

<%= form_for(:user, url: '/user/new') do |f| %>
  <%= render 'shared/error_messages' %>

  <%= f.label :name %>
  <%= f.text_field :name %>

  <%= f.label :citys_id, "City" %>
  <select name="city">
    <% @city.all.each do |t| %>
      <option value="<%= t.id %>"><%= t.city %></option>
    <% end %>
  </select>
end

Перенести

class CreateUser < ActiveRecord::Migration[5.0]
  def change
    create_table :user do |t|
      t.string :name, limit: 80, null: false
      t.belongs_to :citys, null: false
      t.timestamps
  end
end

Сообщение из консоли и браузера:

ActiveRecord::RecordInvalid (Validation failed: City must exist):

Ну, проблема в том, что атрибуты из модели пользователя, которые не являются FK, которые они принимают методом User.save, и атрибуты FK, такие как citys_id, не являются. Затем он дает мне сообщение об ошибке в браузере, в котором говорится, что "Не удалось выполнить проверку. Город должен существовать".

Спасибо

Ответы

Ответ 1

Попробуйте следующее:

belongs_to :city, optional: true

В соответствии с новыми документами:

4.1.2.11: необязательный

Если вы установите для опции: optional значение true, то наличие связанный объект не будет проверен. По умолчанию этот параметр установлен на false.

Ответ 2

Это немного поздно, но вот как это сделать по умолчанию в rails 5:

конфигурации/инициализаторы/new_framework_defaults.rb

Rails.application.config.active_record.belongs_to_required_by_default = false

Надеюсь, это поможет!

Ответ 3

Вам нужно добавить следующее в конец оператора отношения belongs_to:

optional: true

Можно установить это на глобальном уровне, чтобы он работал так же, как и старые версии рельсов, но я бы рекомендовал потратить время, чтобы вручную добавить его к отношениям, которые действительно нужны, поскольку это приведет к меньшему боль в будущем.

Ответ 4

Я обнаружил решение проблемы "Ошибка проверки: класс должен существовать", и это лучше, чем использование:

belongs_to :city, optional: true

4.1.2.11: необязательный

Если вы установите для параметра: optional значение true, то наличие связанного объекта не будет проверено. По умолчанию для этой опции установлено значение false.

вы все равно сделаете проверку на уровне приложения. Я решаю проблему, делая свою собственную проверку в методе создания и изменяя метод user_params:

def create

  @city = City.find(params[:city_id])

  Rails.logger.debug user_params.inspect
  @user = User.new(user_params)

  @user.city_id = @city.id

  if @user.save!
    flash[:success] = "Works!"
    redirect_to '/index'
  else
    render 'new'
  end
end

def user_params
  params.require(:user).permit(:name)
end

Я не тестировал этот код, но он работает в другом проекте. Надеюсь, это поможет другим!

Ответ 5

belongs_to :city, required: false