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:
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
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 ...
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
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