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?

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

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

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"
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.