Remplacer les méthodes d'attribut ActiveRecord

150

Un exemple de ce dont je parle:

class Person < ActiveRecord::Base
  def name=(name)
    super(name.capitalize)
  end
  def name
    super().downcase  # not sure why you'd do this; this is just an example
  end
end

Cela semble fonctionner, mais je viens de lire la section sur le remplacement des méthodes d'attributs dans la documentation ActiveRecord :: Base , et cela suggère d'utiliser les méthodes read_attributeet write_attribute. Je pensais qu'il devait y avoir quelque chose de mal avec ce que je fais dans l'exemple ci-dessus; sinon, pourquoi béniraient-ils ces méthodes comme la «bonne façon» de remplacer les méthodes attributaires? Ils forcent également un langage beaucoup plus laid, donc il doit y avoir une bonne raison ...

Ma vraie question: y a-t-il quelque chose qui ne va pas avec cet exemple?

Ajedi32
la source

Réponses:

211

En écho aux commentaires de Gareth ... votre code ne fonctionnera pas comme écrit. Il devrait être réécrit de cette façon:

def name=(name)
  write_attribute(:name, name.capitalize)
end

def name
  read_attribute(:name).downcase  # No test for nil?
end
Aaron Longwell
la source
Exactement ce dont j'avais besoin. Merci Aaron.
bang du
18
Ce n'est plus vrai. Soit super, soit cela fonctionne maintenant. Cependant, je n'ai pas testé la notation de hachage.
heartpunk
2
Dans les rails 3, la méthode de lecture spécifiée ici par Aaron fonctionne, mais l'écrivain que l'affiche originale a spécifié (donner le nom à super) fonctionne bien, et à mon humble avis, il est plus propre que d'écrire manuellement l'attribut comme le suggère Aaron.
Batkins
1
J'ai testé la méthode de hachage donnée par mipadi ci-dessous et cela fonctionne comme un charme (Rails v 3.2.6)
almathie
N'est-ce pas la bonne réponse? Merci @Aaron, j'ai aussi travaillé pour moi.
Sadiksha Gautam
94

Comme extension de la réponse d'Aaron Longwell, vous pouvez également utiliser une «notation de hachage» pour accéder aux attributs qui ont remplacé les accesseurs et les mutateurs:

def name=(name)
  self[:name] = name.capitalize
end

def name
  self[:name].downcase
end
mipadi
la source
La notation de hachage peut fonctionner, mais self.attributesouffle la pile sur 3.2.16.
jrhorn424
Cela a l'avantage qu'il prend en charge ||=pour le défaut:def name; self[:name] ||= 'anon'; end
Paul Cantrell
Pour moi, cette notation de hachage fonctionne. Mais je ne sais pas pourquoi cela fonctionne. Quelqu'un peut-il expliquer?
radiantshaw
-1

J'ai un plugin rails qui permet de remplacer les attributs avec super comme vous vous en doutez. Vous pouvez le trouver sur github .

À installer:

./script/plugin install git://github.com/chriseppstein/has_overrides.git

Utiliser:

class Post < ActiveRecord::Base

  has_overrides

  module Overrides
    # put your getter and setter overrides in this module.
    def title=(t)
      super(t.titleize)
    end
  end
end

Une fois que vous avez fait cela, les choses fonctionnent:

$ ./script/console 
Loading development environment (Rails 2.3.2)
>> post = Post.new(:title => "a simple title")
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil>
>> post.title = "another simple title"
=> "another simple title"
>> post.title
=> "Another Simple Title"
>> post.update_attributes(:title => "updated title")
=> true
>> post.title
=> "Updated Title"
>> post.update_attribute(:title, "singly updated title")
=> true
>> post.title
=> "Singly Updated Title"
Chriseppstein
la source