66 votes

La validation a échoué La classe doit exister

J'ai eu des (heures de) problèmes avec les associations dans Rails. J'ai trouvé beaucoup de problèmes similaires, mais je ne pouvais pas appliquer pour mon cas :

La classe de la ville :

class City < ApplicationRecord
  has_many :users
end

Classe de l'utilisateur :

class User < ApplicationRecord
  belongs_to :city

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

Contrôleur des utilisateurs :

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

Vue des utilisateurs :

<%= 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

Migrer :

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

Message de la console et du navigateur :

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

Le problème est que les attributs du modèle de l'utilisateur qui ne sont pas des FK sont acceptés par la méthode User.save, et les attributs FK comme citys_id ne le sont pas. Cela me donne un message d'erreur dans le navigateur disant que "Validation failed City must exist".

Thanks

0 votes

125voto

Igor_Marques Points 912

Essayez ce qui suit :

belongs_to :city, optional: true

Selon le nouveaux documents :

4.1.2.11 :facultatif

Si vous attribuez la valeur true à l'option :optional, la présence de la balise objet associé ne sera pas validée. Par défaut, cette option est définie par défaut.

1 votes

Hey Igor c'est sympa de voir un BR ici :) Merci pour votre réponse. Cela a marché ! J'ai trouvé cette réponse plus tôt, mais je n'ai pas essayé jusqu'à maintenant. La raison est qu'il me semble que ceci option invalider la validation de l'attributaire au niveau du serveur. J'ai donc vérifié pour être sûr, lorsque je donne une valeur erronée à la clé étrangère city_id, le message d'erreur s'affiche juste après que la base de données ait essayé de faire une requête d'insertion, il me semble que c'est une validation au niveau de la base de données. De toute façon, je vais faire ma propre validation au niveau du serveur pour résoudre ce problème. J'aimerais vous donner un UPVOTE, mais je n'ai pas assez de points :( haha

1 votes

Ohhh, je ne le savais pas ! hahaha bien :)

4 votes

Argh, c'est un gotcha assez ennuyeux. Sur FactoryGirl si vous créez simplement une usine pour User sans cet extrait, dans le belongs_to vous obtiendrez cette erreur. Bien vu !

16voto

Jeremie Points 1232

C'est un peu tard mais c'est comment désactiver cette fonction par défaut dans les rails 5 :

config/initializers/new_framework_defaults.rb

Rails.application.config.active_record.belongs_to_required_by_default = false

Au cas où vous ne voudriez pas ajouter optional: true à tous vos belongs_to .

J'espère que cela vous aidera !

0 votes

J'ai effectué la mise à niveau vers Mac OS Mojave hier et je reçois maintenant ces erreurs de validation, bien que mon projet ait défini cette valeur sur false (depuis que nous avons effectué la mise à niveau vers Rails 5, il y a longtemps). Quelqu'un sait-il comment cela se produit ?

4voto

David Kane Points 61

Vous devez ajouter le texte suivant à la fin de l'instruction de relation belongs_to :

optional: true

Il est possible de définir cette option à un niveau global afin qu'elle fonctionne de la même manière que les anciennes versions de rails, mais je vous recommande de prendre le temps de l'ajouter manuellement aux relations qui en ont vraiment besoin, car cela sera moins pénible à l'avenir.

3voto

J'ai trouvé une solution au problème "Validation failed : Class must exist" et c'est mieux que l'utilisation :

belongs_to :city, optional: true

4.1.2.11 :facultatif

Si vous attribuez la valeur true à l'option :optional, la présence de l'objet associé ne sera pas validée. Par défaut, cette option est définie sur false.

parce que vous faites toujours une validation au niveau de l'application. Je résous le problème en créant ma propre validation dans la méthode create et en modifiant la méthode 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

Je n'ai pas testé ce code, mais il fonctionne dans un autre de mes projets. J'espère qu'il pourra aider d'autres personnes !

1voto

Alex P Points 344
belongs_to :city, required: false

3 votes

Veuillez essayer de donner une explication pour répondre à la question et ne pas vous contenter de poster un code. Merci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X