Comment puis-je écraser une méthode getter dans un modèle ActiveRecord?


98

J'essaie de remplacer une méthode getter pour un modèle ActiveRecord. J'ai un attribut appelé namedans le modèle Categoryet j'aimerais pouvoir faire quelque chose comme ceci:

def name
  name_trans || name
end

Si l' name_transattribut n'est pas nul, alors renvoyez-le, sinon renvoyez l' nameattribut. Comment ferais-je ça?

Cela devrait alors être appelé normalement comme ceci:

@category.name

Réponses:



98

Mise à jour: La méthode préférée selon le guide de style des rails est d'utiliser à la self[:name]place de read_attributeet write_attribute. Je vous encourage à sauter ma réponse et à préférer celle-ci .


Vous pouvez le faire exactement comme ça, sauf que vous devez utiliser read_attributepour récupérer la valeur de l'attribut name et éviter l'appel récursif à la nameméthode:

def name 
  name_trans || read_attribute(:name)
end

2
Toute idée pourquoi Rubocop préfère self[:name]plus read_attribute[:name]?
Zack Xu

18

Je voudrais ajouter une autre option pour écraser la méthode getter, qui est simplement : super.

def name
  name_trans || super
end

cela fonctionne non seulement sur la méthode getter des attributs, mais aussi sur les méthodes getter des associations , aussi。


1
C'est ce que les guides Rails recommandent actuellement, pour les getters ET les setters: api.rubyonrails.org/classes/ActiveRecord/…
sandre89

5

Remplacer le getter et utiliser read_attributene fonctionne pas pour les associations, mais vous pouvez utiliser à la alias_method_chainplace.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Pouvez-vous donner un bon exemple ...?
Arup Rakshit

Bien. Je viens de voir le doco . Maintenant, si j'appelle namel'objet modèle, lequel sera appelé - name_with_overrideou name_without_override?
Arup Rakshit

1
nameva maintenant appeler name_with_override. Si vous souhaitez appeler la méthode d'origine pour une raison quelconque, vous pouvez appeler name_without_override.
Patrick Oscity

OI see .. Merci pour vos réponses //
Arup Rakshit

2

Si vous utilisez des attributs de magasin comme celui-ci

store :settings, accessors: [:volume_adjustment] 

ou en utilisant des gemmes comme hstore_accessor un lien de gemme

Vous avez donc fini par utiliser la storeméthode sur le modèle, puis pour remplacer les méthodes que vous ne pouvez pas utiliser self.read_attribute, vous devez utiliser à la place supercomme ça:

def partner_percentage
  super.to_i || 10
end

0

Si quelqu'un veut mettre à jour la valeur après name_transdans la méthode getter, vous pouvez utiliser self [: name] =.

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

0

Vous pouvez utiliser la méthode read_attribute de Rails. Documentation sur les rails


Bien que ce lien puisse répondre à la question, les réponses aux liens uniquement ne sont pas autorisées sur SO, veuillez ajouter du contexte à votre réponse à partir de ce qui se cache derrière ce lien. Merci! :)
AJT82
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.