Sostituisci metodi di attributo ActiveRecord


150

Un esempio di ciò di cui sto parlando:

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

Questo sembra funzionare, ma ho appena letto la sezione sulla sostituzione dei metodi di attributo nei documenti ActiveRecord :: Base e mi suggerisce di usare i metodi read_attributee write_attribute. Ho pensato che ci fosse qualcosa di sbagliato in ciò che sto facendo nell'esempio sopra; altrimenti, perché dovrebbero benedire questi metodi come il "modo giusto" per sovrascrivere i metodi di attributo? Stanno anche forzando un linguaggio molto più brutto, quindi ci deve essere una buona ragione ...

La mia vera domanda: c'è qualcosa di sbagliato in questo esempio?

Risposte:


211

Facendo eco ai commenti di Gareth ... il tuo codice non funzionerà come scritto. Dovrebbe essere riscritto in questo modo:

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

def name
  read_attribute(:name).downcase  # No test for nil?
end

Esattamente quello di cui avevo bisogno. Grazie Aaron.
bong,

18
Questo non è più vero. O super o questo funziona ora. Non ho testato la notazione hash, tuttavia.
Heartpunk,

2
In rotaie 3, il metodo del lettore specificato qui da Aaron funziona, ma lo scrittore che il poster originale specificato (dando il nome a super) funziona bene e IMHO è più pulito della scrittura manuale dell'attributo come suggerisce Aaron.
Batkins,

1
Ho testato il metodo hash fornito da mipadi di seguito e funziona come un incantesimo (Rails v 3.2.6)
almathie

Non è la risposta giusta? Grazie @Aaron, ha funzionato anche per me.
Sadiksha Gautam,

94

Come estensione della risposta di Aaron Longwell, puoi anche usare una "notazione hash" per accedere ad attributi che hanno scavalcato accessori e mutatori:

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

def name
  self[:name].downcase
end

La notazione hash può funzionare, ma self.attributefa esplodere la pila 3.2.16.
jrhorn424,

Questo ha il vantaggio che supporta ||=per il default:def name; self[:name] ||= 'anon'; end
Paul Cantrell,

Per me, questa notazione hash funziona. Ma non conosco il motivo per cui funziona. Qualcuno può spiegare?
radiantshaw,


-1

Ho un plug-in di rotaie che fa funzionare l'override degli attributi con Super come ti aspetteresti. Puoi trovarlo su github .

Installare:

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

Usare:

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

Una volta che hai fatto che le cose funzionano e basta:

$ ./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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.