Comment définir les valeurs par défaut dans Rails?

J’essaie de trouver le meilleur moyen de définir les valeurs par défaut pour les objects dans Rails.

Le mieux que je puisse penser est de définir la valeur par défaut dans la new méthode du contrôleur.

Quelqu’un at-il des commentaires si cela est acceptable ou s’il existe une meilleure façon de le faire?

“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 que cette valeur par défaut pour cette colonne de cette table, la configuration la plus simple dans un fichier de migration de firebase database est la suivante:

 class SetDefault < ActiveRecord::Migration def self.up change_column :people, :last_name, :type, :default => "Doe" end def self.down # You can't currently remove default values in Rails raise ActiveRecord::IrreversibleMigration, "Can't remove the default" end end 

Comme ActiveRecord détecte automatiquement vos propriétés de table et de colonne, le même défaut sera défini dans n’importe quel modèle qui l’utilise dans n’importe quelle application Rails standard.

Cependant, si vous souhaitez uniquement définir des valeurs par défaut dans des cas spécifiques – par exemple, un modèle hérité qui partage une table avec d’autres -, une autre méthode élégante consiste à le faire directement dans votre code Rails lorsque l’object modèle est créé:

 class GenericPerson < Person def initialize(attributes=nil) attr_with_defaults = {:last_name => "Doe"}.merge(atsortingbutes) super(attr_with_defaults) end end 

Ensuite, lorsque vous faites un GenericPerson.new() , l’atsortingbut “Doe” passe toujours à Person.new() moins que vous ne le Person.new() par quelque chose d’autre.

Sur la base de la réponse de SFEley, voici une mise à jour / fixe pour les nouvelles versions de Rails:

 class SetDefault < ActiveRecord::Migration def change change_column :table_name, :column_name, :type, default: "Your value" end end 

Tout d’abord, vous ne pouvez pas surcharger l’ initialize(*args) car elle n’est pas appelée dans tous les cas.

Votre meilleure option est de mettre vos parameters par défaut dans votre migration:

 add_column :accounts, :max_users, :integer, :default => 10 

Deuxièmement, il est préférable de placer des valeurs par défaut dans votre modèle, mais cela ne fonctionnera qu’avec des atsortingbuts initialement nuls. Vous pouvez avoir des problèmes comme je l’ai fait avec les colonnes boolean :

 def after_initialize if new_record? max_users ||= 10 end end 

Vous avez besoin du new_record? donc les valeurs par défaut ne remplacent pas les valeurs chargées depuis la firebase database.

Vous avez besoin de ||= pour empêcher Rails de remplacer les parameters passés à la méthode initialize.

Vous pouvez également essayer change_column_default dans vos migrations (testé dans Rails 3.2.8):

 class SetDefault < ActiveRecord::Migration def up # Set default value change_column_default :people, :last_name, "Smith" end def down # Remove default change_column_default :people, :last_name, nil end end 

Change_column_default Documents de l'API Rails

Si vous faites référence à des objects ActiveRecord, vous avez deux possibilités:

1. Utilisez un paramètre: default dans la firebase database

PAR EXEMPLE

 class AddSsl < ActiveRecord::Migration def self.up add_column :accounts, :ssl_enabled, :boolean, :default => true end def self.down remove_column :accounts, :ssl_enabled end end 

Plus d’infos ici: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

2. Utiliser un rappel

EG before_validation_on_create

Plus d’infos ici: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147

Dans Ruby on Rails v3.2.8, en utilisant le callback after_initialize ActiveRecord, vous pouvez appeler une méthode dans votre modèle qui affectera les valeurs par défaut d’un nouvel object.

Le rappel after_initialize est déclenché pour chaque object trouvé et instancié par un finder, after_initialize étant déclenché après l’instanciation de nouveaux objects ( voir Callbacks ActiveRecord ).

Donc, l’OMI devrait ressembler à ceci:

 class Foo < ActiveRecord::Base after_initialize :assign_defaults_on_new_Foo ... attr_accessible :bar ... private def assign_defaults_on_new_Foo # required to check an attribute for existence to weed out existing records self.bar = default_value unless self.attribute_whose_presence_has_been_validated end end 

Foo.bar = default_value pour cette instance sauf si l'instance contient un atsortingbute_whose_presence_has_been_validated précédemment lors de la sauvegarde / mise à jour. La valeur par default_value sera alors utilisée conjointement avec votre vue pour afficher le formulaire à l'aide de la valeur par default_value de l'atsortingbut de bar .

Au mieux, c'est du piratage ...

EDIT - utilise 'new_record?' vérifier si l'instanciation d'un nouvel appel

Au lieu de vérifier une valeur d'atsortingbut, utilisez le new_record? méthode intégrée avec des rails. Ainsi, l'exemple ci-dessus devrait ressembler à ceci:

 class Foo < ActiveRecord::Base after_initialize :assign_defaults_on_new_Foo, if: 'new_record?' ... attr_accessible :bar ... private def assign_defaults_on_new_Foo self.bar = default_value end end 

C'est beaucoup plus propre. Ah, la magie de Rails - c'est plus intelligent que moi.

Pour les champs booléens dans Rails 3.2.6 au moins, cela fonctionnera dans votre migration.

 def change add_column :users, :eula_accepted, :boolean, default: false end 

Mettre un 1 ou un 0 pour un défaut ne fonctionnera pas ici, puisque c’est un champ booléen. Ce doit être une valeur true ou false .

Si vous définissez uniquement des valeurs par défaut pour certains atsortingbuts d’un modèle sauvegardé dans une firebase database, j’utiliserais des valeurs de colonne SQL par défaut. Pouvez-vous préciser les types de valeurs par défaut que vous utilisez?

Il y a un certain nombre d’approches pour le gérer, ce plugin ressemble à une option intéressante.

La suggestion de remplacer le nouveau / initialiser est probablement incomplète. Les appels vont (fréquemment) appeler allocate pour les objects ActiveRecord, et les appels à allouer n’entraîneront pas d’initialisation des appels.

Si vous parlez d’objects ActiveRecord, jetez un oeil à la méthode after_initialize.

Ces billets de blog (pas les miens) sont utiles:

Valeurs par défaut Constructeurs par défaut non appelés

[Edit: SFEley fait remarquer que Rails examine réellement la valeur par défaut dans la firebase database lorsqu’il instancie un nouvel object en mémoire – je ne l’avais pas compris.]

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 la firebase database. Donc, il se comporte comme ça

 a = Item.new a.published_at # => my default value a = Item.new(:published_at => nil) a.published_at # => nil 

Dans la mesure où le rappel after_initialize est appelé après la définition des atsortingbuts à partir d’arguments, il était impossible de savoir si l’atsortingbut est nul car il n’a jamais été défini ou parce qu’il a été défini intentionnellement comme nul. J’ai donc dû aller un peu à l’intérieur et je suis venu avec cette solution simple.

 class Item < ActiveRecord::Base def self.column_defaults super.merge('published_at' => Time.now) end end 

Fonctionne très bien pour moi. (Rails 3.2.x)

Un moyen potentiellement meilleur / plus propre que les réponses proposées est d’écraser l’accesseur, comme ceci:

 def status self['name_of_var'] || 'desired_default_value' end 

Voir “Ecraser les accesseurs par défaut” dans la documentation ActiveRecord :: Base et plus encore sur StackOverflow lors de l’utilisation de self .

J’ai répondu à une question similaire ici . Une manière propre de le faire est d’utiliser Rails attr_accessor_with_default

 class SOF attr_accessor_with_default :is_awesome,true end sof = SOF.new sof.is_awesome => true 

METTRE À JOUR

attr_accessor_with_default est devenu obsolète dans Rails 3.2 .. vous pouvez le faire à la place avec du Ruby pur

 class SOF attr_writer :is_awesome def is_awesome @is_awesome ||= true end end sof = SOF.new sof.is_awesome #=> true 

Si vous parlez d’objects ActiveRecord, j’utilise le joyau ‘atsortingbute-defaults’.

Documentation et téléchargement: https://github.com/bsm/atsortingbute-defaults

Vous pouvez utiliser le joyau rails_default_value. par exemple:

 class Foo < ActiveRecord::Base # ... default :bar => 'some default value' # ... end 

https://github.com/keithrowell/rails_default_value

Si vous avez affaire à un modèle, vous pouvez utiliser l’API Atsortingutes dans Rails 5+ http://api.rubyonrails.org/classes/ActiveRecord/Atsortingbutes/ClassMethods.html#method-i-atsortingbute

Il suffit d’append une migration avec un nom de colonne correct, puis dans le modèle, le définir avec:

 class StoreListing < ActiveRecord::Base attribute :country, :string, default: 'PT' end 

Vous pouvez remplacer le constructeur du modèle ActiveRecord.

Comme ça:

 def initialize(*args) super(*args) self.atsortingbute_that_needs_default_value ||= default_value self.atsortingbute_that_needs_another_default_value ||= another_default_value #ad nauseum end