J'essaie de trouver le meilleur moyen de définir des valeurs par défaut pour les objets dans Rails.
Le mieux que je puisse penser est de définir la valeur par défaut dans la new
méthode dans le contrôleur.
Quelqu'un a-t-il quelque chose à dire si cela est acceptable ou s'il existe une meilleure façon de le faire?
ruby-on-rails
ruby
biagidp
la source
la source
Réponses:
«Correct» est un mot dangereux en Ruby. Il y a généralement plus d'une façon de faire quoi que ce soit. Si vous savez que vous voudrez toujours cette valeur par défaut pour cette colonne sur cette table, les définir dans un fichier de migration de base de données est le moyen le plus simple:
Étant donné qu'ActiveRecord détecte automatiquement les propriétés de votre table et de votre colonne, la même valeur par défaut sera définie dans tout modèle l'utilisant dans n'importe quelle application Rails standard.
Cependant, si vous ne voulez que des valeurs par défaut définies dans des cas spécifiques - par exemple, c'est un modèle hérité qui partage une table avec d'autres - alors une autre manière élégante est de le faire directement dans votre code Rails lorsque l'objet de modèle est créé:
Ensuite, lorsque vous faites un
GenericPerson.new()
, il va toujours ruisseler l'attribut "Doe" jusqu'àPerson.new()
moins que vous ne le remplaciez par autre chose.la source
.new
méthode de classe. La discussion de ce billet de blog sur l'appel direct d'ActiveRecord.allocate
portait sur les objets de modèle chargés avec les données existantes de la base de données. ( Et c'est une idée terrible pour ActiveRecord de fonctionner de cette façon, OMI. Mais ce n'est pas la question.)change_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520change_column :people, :last_name, :string, default: "Doe"
Sur la base de la réponse de SFEley, en voici une mise à jour / corrigée pour les nouvelles versions de Rails:
la source
change_column
peut être tout à fait «structurant», l'opération inverse ne peut être déduite. Si vous n'êtes pas sûr, testez-le simplement en exécutantdb:migrate
etdb:rollback
juste après. Réponse acceptée comme le même résultat mais au moins c'est supposé!up
etdown
comme décrit ci-dessus de @GoBustoTout d'abord, vous ne pouvez pas surcharger
initialize(*args)
car il n'est pas appelé dans tous les cas.Votre meilleure option est de mettre vos valeurs par défaut dans votre migration:
Le deuxième mieux est de placer des valeurs par défaut dans votre modèle, mais cela ne fonctionnera qu'avec des attributs initialement nuls. Vous pouvez avoir des problèmes comme je l'ai fait avec les
boolean
colonnes:Vous en avez besoin
new_record?
pour que les valeurs par défaut ne remplacent pas les valeurs chargées à partir de la base de données.Vous devez
||=
empêcher Rails de remplacer les paramètres passés dans la méthode d'initialisation.la source
after_initiation :your_method_name
.... 2 utilisationself.max_users ||= 10
after_initialize do
au lieu dedef after_initialize
Vous pouvez également essayer
change_column_default
dans vos migrations (testé dans Rails 3.2.8):Documentation sur l'API change_column_default Rails
la source
Si vous faites référence à des objets ActiveRecord, vous avez (plus de) deux façons de procéder:
1. Utilisez un: paramètre par défaut dans le DB
PAR EXEMPLE
Plus d'informations ici: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
2. Utilisez un rappel
PAR EXEMPLE
before_validation_on_create
Plus d'informations ici: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
la source
Dans Ruby on Rails v3.2.8, en utilisant le
after_initialize
rappel ActiveRecord, vous pouvez appeler une méthode dans votre modèle qui attribuera les valeurs par défaut pour un nouvel objet.Donc, IMO, cela devrait ressembler à quelque chose comme:
Foo.bar = default_value
pour cette instance, sauf si l'instance contient uneattribute_whose_presence_has_been_validated
sauvegarde / mise à jour précédemment en cours. Ledefault_value
sera ensuite utilisé avec votre vue pour rendre le formulaire en utilisantdefault_value
pour l'bar
attribut.Au mieux, c'est du piratage ...
EDIT - utilisez 'new_record?' pour vérifier si l'instanciation à partir d'un nouvel appel
Au lieu de vérifier une valeur d'attribut, utilisez la
new_record?
méthode intégrée avec des rails. Ainsi, l'exemple ci-dessus devrait ressembler à:C'est beaucoup plus propre. Ah, la magie de Rails - c'est plus intelligent que moi.
la source
after_initialize
rappel ici? La documentation Rails sur les rappels a un exemple de définition de la valeur par défautbefore_create
sans vérification de condition supplémentaireSubscription
after_initialize
, au lieu dubefore_create
rappel, est que nous voulons définir une valeur par défaut pour l' utilisateur (à utiliser dans une vue) lorsqu'il crée de nouveaux objets. Lebefore_create
rappel est appelé après que l' utilisateur a reçu un nouvel objet, fourni son entrée et soumis l'objet pour la création au contrôleur. Le contrôleur vérifie ensuite les éventuelsbefore_create
rappels. Cela semble contre-intuitif, mais c'est une chose de nomenclature - sebefore_create
réfère à l'create
action. L'instanciation d'un nouvel objet ne fait pascreate
l'objet.Pour les champs booléens dans Rails 3.2.6 au moins, cela fonctionnera dans votre migration.
Mettre un
1
ou0
pour une valeur par défaut ne fonctionnera pas ici, car il s'agit d'un champ booléen. Ce doit être une valeurtrue
oufalse
.la source
Dans le cas où vous avez affaire à un modèle, vous pouvez utiliser l'API Attriutes dans Rails 5+ http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
ajoutez simplement une migration avec un nom de colonne approprié, puis dans le modèle, définissez-la avec:
la source
Générer une migration et une utilisation
change_column_default
, c'est succinct et réversible:la source
Si vous définissez simplement des valeurs par défaut pour certains attributs d'un modèle basé sur une base de données, j'envisagerais d'utiliser les valeurs de colonne par défaut SQL - pouvez-vous clarifier les types de valeurs par défaut que vous utilisez?
Il existe un certain nombre d'approches pour le gérer, ce plugin ressemble à une option intéressante.
la source
La suggestion de remplacer new / initialize est probablement incomplète. Rails appellera (fréquemment) allocate pour les objets ActiveRecord, et les appels à allouer n'entraîneront pas d'appels à initialiser.
Si vous parlez d'objets ActiveRecord, jetez un œil à la substitution de after_initialize.
Ces articles de blog (pas les miens) sont utiles:
Valeurs par défaut Constructeurs par défaut non appelés
[Edit: SFEley souligne que Rails regarde réellement la valeur par défaut dans la base de données quand il instancie un nouvel objet en mémoire - je ne l'avais pas réalisé.]
la source
J'avais besoin de définir une valeur par défaut comme si elle était spécifiée comme valeur de colonne par défaut dans DB. Donc ça se comporte comme ça
Comme le rappel after_initialize est appelé après avoir défini des attributs à partir d'arguments, il n'y avait aucun moyen de savoir si l'attribut est nul car il n'a jamais été défini ou parce qu'il a été intentionnellement défini comme nul. J'ai donc dû fouiller un peu à l'intérieur et suis venu avec cette solution simple.
Fonctionne très bien pour moi. (Rails 3.2.x)
la source
Un moyen potentiel potentiellement encore meilleur / plus propre que les réponses proposées est d'écraser l'accesseur, comme ceci:
Voir «Écraser les accesseurs par défaut» dans la documentation ActiveRecord :: Base et plus de StackOverflow sur l'utilisation de self .
la source
J'ai répondu à une question similaire ici .. une façon simple de le faire est d'utiliser Rails attr_accessor_with_default
METTRE À JOUR
attr_accessor_with_default est obsolète dans Rails 3.2 .. vous pouvez le faire à la place avec du Ruby pur
la source
attr_accessor_with_default
est obsolète à partir de rails> 3.1.0Si vous parlez d'objets ActiveRecord, j'utilise la gemme «attributs par défaut».
Documentation et téléchargement: https://github.com/bsm/attribute-defaults
la source
Vous pouvez utiliser la gemme rails_default_value. par exemple:
https://github.com/keithrowell/rails_default_value
la source
Vous pouvez remplacer le constructeur du modèle ActiveRecord.
Comme ça:
la source