Dans Rails, existe-t-il un moyen de spécifier un TYPE que vous souhaitez qu'un attr_accessor soit et de le valider à l'aide de la validation Rails intégrée ?
-
13-11-2019 - |
Question
Je n'ai jamais réussi à trouver une bonne façon de procéder, alors j'ai pensé demander.
Par exemple, dans un modèle ActiveRecord, les attributs basés sur la base de données sont automatiquement convertis en types appropriés basés sur la base de données.Si j'ai un Category
modèle, et il a quelques attributs, disons name
et category_id
, si je fais comme ça :
Category.new(params[:category])
Rails le sait name
est une chaîne et category_id
est un entier.
Disons que j'ai plusieurs attributs transitoires/synthétiques que je souhaite valider, et qu'ils ont des types spécifiques.Je souhaite les soumettre à partir d'un formulaire et j'aimerais qu'ils soient automatiquement convertis en chaîne, en entier ou en date (par exemple) en fonction de la façon dont ils sont définis.
Si je devais déclarer quelque chose dans un modèle Rails comme :
attr_accessor :some_number_variable
attr_accessor :some_date
Existe-t-il un moyen intégré de dire à Rails "J'aimerais que vous transformiez le premier en un entier et le second en une date, quand je vais Category.new(params[:category])
" tant que params[:category][:some_number_variable]
et params[:category][:some_date]
font partie des données soumises au contrôleur (je me rends compte que l'exemple Date pourrait être un peu plus délicat étant donné les nombreux formats de date disponibles).
La solution
Aucune des réponses ne répond vraiment à la question.Je crois que la bonne réponse à ces questions est simplement « Non ».Les réponses abordent toutes deux des solutions de contournement potentielles au fait que la réponse à la question est « Non », et les deux sont des commentaires/idées valables.
Autres conseils
Depuis Rails 5, il y a le API d'attribut que vous pouvez utiliser comme ceci :
class SomeModel < ActiveRecord::Base
attribute :a_checkbox_name, :boolean, default: false
end
Vous pouvez définir des valeurs par défaut et définir vos propres types, entre autres choses intéressantes.Ensuite, vous pouvez valider ces attributs (virtuels ou non) comme n'importe quel autre attribut soutenu par une base de données.
attr_accesor
crée simplement des méthodes de lecture/écriture, et cela vient de Rubis, pas Rails.La méthode Rails qui, je crois, est souvent confuse est attr_accessible
qui sert un but différent.Si vous souhaitez effectuer un cast lorsque l'attribut est lu, vous pouvez simplement remplacer le lecteur.
attr_accessor :some_number_variable
def some_number_variable
@some_number_variable.to_i
end
Cela vous donnera au moins l'écrivain gratuitement.C'est la meilleure solution que je connaisse pour ce que (je pense) vous décrivez.
MODIFIER:En ce qui concerne la validation, je pense que si vous utilisez Rails 3, il vous sera beaucoup plus facile d'effectuer une validation sur ce type d'attributs (je ne l'ai pas fait donc je ne peux pas le dire avec certitude).Maintenant que les validations ne sont plus directement liées à ActiveRecord, je le croirais possible.
Je suppose que par attribut « transitoire/synthétique », vous entendez un attribut virtuel ?
Si tel est le cas, il n'existe aucune fonction Rails intégrée qui fasse cela à laquelle je puisse penser, mais une solution serait simplement d'écrire un module pour ces attributs et de l'inclure dans le modèle.Ou s'il devait être dynamique, vous pouvez appeler l'attribut quelque chose comme :some_variable_integer, puis gérer ces attributs dynamiques avec method_missing, lire le nom de la méthode et le convertir dans le type requis.
À mon avis, c'est un peu compliqué, donc les validations dans le modèle sont vraiment votre meilleur pari si ce que vous cherchez à faire peut les prendre en charge.
utiliser avant_créer..
class Category
attr_accessor :some_number_variable, :some_date
before_create :validate
private
def validate
return unless !!params[:category]
#do variable casting here
end
end
Ajoutez ce qui suit à votre modèle :
columns_hash["birth_date"] = ActiveRecord::ConnectionAdapters::Column.new("birth_date", nil, "date")
référence: Rails ActiveRecord :: MultiparameterAssignmentErrors