web-dev-qa-db-fra.com

Comment initialiser un ActiveRecord avec des valeurs dans Rails?

En clair Java j'utiliserais:

public User(String name, String email) {
  this.name = name;
  this.email = f(email);
  this.admin = false;
}

Cependant, je ne pouvais pas trouver un moyen standard simple de le faire dans Rails (3.2.3), avec ActiveRecords.

1. remplacer initialiser

def initialize(attributes = {}, options = {})
  @name  = attributes[:name]
  @email = f(attributes[:email])
  @admin = false
end

mais il peut être manqué lors de la création d'un enregistrement à partir de la base de données

2. en utilisant le after_initialize rappeler

en le remplaçant:

def after_initialize(attributes = {}, options = {})
  ...
end

ou avec la macro:

after_initialize : my_own_little_init
def my_own_little_init(attributes = {}, options = {})
  ...
end

mais il peut y avoir certains problèmes de dépréciation .

Il existe quelques autres liens dans SO , mais ils peuvent être obsolètes.


Donc, quelle est la méthode correcte/standard à utiliser?

25
Asaf

Vos valeurs par défaut doivent être définies dans votre schéma lorsqu'elles s'appliqueront à TOUS les enregistrements. Donc

def change
  creates_table :posts do |t|
    t.boolean :published, default: false
    t.string :title
    t.text :content
    t.references :author
    t.timestamps
  end
end

Ici, chaque nouveau message aura un faux pour être publié. Si vous souhaitez des valeurs par défaut au niveau de l'objet, il est préférable d'utiliser des implémentations de style Factory:

User.build_admin(params)

def self.build_admin(params)
  user = User.new(params)
  user.admin = true
  user
end
17
Jesse Wolgamott

Selon Rails Guides, la meilleure façon de le faire est avec le after_initialize . Parce qu'avec l'initialisation, nous devons déclarer le super, il est donc préférable d'utiliser le rappel .

15
Mauro George

Une solution que j'aime est via les étendues:

class User ...
   scope :admins, where(admin: true)

Ensuite, vous pouvez faire les deux: créer un nouvel utilisateur dans le statut d'administrateur (c'est-à-dire avec admin == true) via User.admins.new(...) et également récupérer tous vos administrateurs de la même manière User.admins.

Vous pouvez créer quelques étendues et en utiliser peu comme modèles pour créer/rechercher. Vous pouvez également utiliser default_scope Avec la même signification, mais sans nom car il est appliqué par défaut.

5
jdoe

Cela fonctionnera en Rails 4.

def initialize(params)
    super
    params[:name] = params[:name] + "xyz" 
    write_attribute(:name, params[:name]) 
    write_attribute(:some_other_field, "stuff")
    write_attribute(:email, params[:email])
    write_attribute(:admin, false)
end
4
Harry Fairbanks

Je cherchais quelque chose de similaire ce matin. Bien que la définition d'une valeur par défaut dans la base de données fonctionnera évidemment, cela semble rompre avec la convention de Rails selon laquelle l'intégrité des données (et donc les valeurs par défaut?) Est gérée par l'application.

Je suis tombé sur ce post . Comme vous ne voudrez peut-être pas enregistrer l'enregistrement dans la base de données immédiatement, je pense que la meilleure façon est d'écraser la méthode d'initialisation avec un appel à write_attribute().

def initialize
  super
  write_attribute(name, "John Doe")
  write_attribute(email,  f(email))
  write_attribute(admin, false)
end
4
clekstro