2015-12-22 5 views
6

In PHP, posso impostare un attributo (che non è una colonna nel database) su un modello. Per esempio (codice PHP),Imposta attributo non database per modello di rota senza `attr_accessor`

$user = new User; 
$user.flag = true; 

Ma in rotaie, quando ho impostato qualsiasi attributo che non esiste nel database, si genera un errore undefined method flag. C'è il metodo attr_accessor, ma cosa succede se ho bisogno di circa dieci attributi temporanei?

+0

Avere non colonna gli attributi nell'oggetto sono un odore di codice, almeno per me. Ecco qualcosa che riguarda: https://www.youtube.com/watch?v=SvL_aZt3zyU –

+1

Normalmente non userete $ -variables in rails. Stai mescolando insieme codice php e ruby? –

+0

@MaxWilliams No, questo è un esempio di PHP. – sawa

risposta

3

Questo è previsto perché è come ActiveRecord funziona in base alla progettazione. Se è necessario impostare attributi arbitrari, è necessario utilizzare un diverso tipo di oggetti.

Ad esempio, Ruby fornisce una libreria denominata OpenStruct che consente di creare oggetti in cui è possibile assegnare chiavi/valori arbitrari. Si consiglia di utilizzare tale libreria e quindi convertire l'oggetto in un'istanza ActiveRecord corrispondente solo se/quando è necessario salvare nel database.

Non tentare di modellare ActiveRecord per comportarsi come appena descritto perché semplicemente non è stato progettato per comportarsi in questo modo. Sarebbe un errore cargo culting dalla tua attuale conoscenza di PHP.

+0

grazie mille, non conosco mai la lib di 'OpenStruct' fino a quando non me lo hai detto. Ho combinato la soluzione con la soluzione @Nimir e funziona perfettamente: D 'attr_accessor: flag after_initialize do | utente | self.flag = OpenStruct.new FINE' E posso impostare/ottenere l'attributo temperatura bandiera utilizzando '@user.flag.hello = "Ciao Mondo" ' ps: sr, io non so come per formattare il codice – user3783161

0

Se sono necessari gli attributi temporanei, è possibile aggiungerli all'oggetto singleton.

model = Model.new 

class << model 
    attr_accessor :name 
end 
1

Tutto ciò che attr_accessor non fa altro che aggiungere metodi getter e setter che utilizzano una variabile di istanza, ad esempio, questo

attr_accessor :flag 

aggiungerà questi metodi:

def flag 
    @flag 
end 

def flag=(val) 
    @flag = val 
end 

È possibile scrivere questi metodi da soli se vuoi, e fagli fare qualcosa di più interessante del solo memorizzare il valore in un'istanza var, se vuoi.

2

Come hanno spiegato i ragazzi, attr_accessor è solo un rapido setter e getter.

Possiamo impostare il nostro modello attr_accessor su inizializzazione di record per essere un Ruby#Hash ad esempio utilizzando ActiveRecord#After_initilize method in modo da ottenere una maggiore flessibilità sulla memorizzazione temporanea di valori (idea credit to this answer).

Qualcosa di simile:

class User < ActiveRecord::Base 

    attr_accessor :vars 

    after_initialize do |user| 
    self.vars = Hash.new 
    end 

end 

Ora si potrebbe fare:

user = User.new 

#set 
user.vars['flag'] = true 

#get 
user.vars['flag'] 
#> true 
5

ma cosa accadrà se ho bisogno di una decina di attributi temporanei?

#app/models/user.rb 
class User < ActiveRecord::Base 
    attr_accessor :flag, :other_attribute, :other_attribute2, :etc... 
end 

attr_accessor crea "virtual" attributes in Rails - non esistono nel database, ma sono presenti nel modello.

Come con gli attributi del db, attr_accessor solo crea una serie di setter & getter (esempio) i metodi nella classe, che è possibile chiamare & interagiscono con quando la classe viene inizializzato:

#app/models/user.rb 
class User < ActiveRecord::Base 
    attr_accessor :flag 

    # getter 
    def flag 
    @flag 
    end 

    # setter 
    def flag=(val) 
    @flag = val 
    end 
end 
Problemi correlati