Molte persone su questo thread e su Google spiegano molto bene che attr_accessible
specifica una whitelist di attributi che possono essere aggiornati in blocco ( tutti gli attributi di un modello a oggetti contemporaneamente ) Questo è principalmente (e solo) per proteggere la tua applicazione dall'exploit pirata "Assegnazione di massa".
Questo è spiegato qui nel documento ufficiale di Rails: Assegnazione di massa
attr_accessor
è un codice rubino per (rapidamente) creare metodi setter e getter in una classe. È tutto.
Ora, ciò che manca come spiegazione è che quando crei in qualche modo un collegamento tra un modello (Rails) con una tabella di database, non hai MAI, MAI MAI, MAI PIÙ bisogno attr_accessor
nel tuo modello di creare setter e getter per poter modificare il tuo record della tabella.
Questo perché il tuo modello eredita tutti i metodi dalla ActiveRecord::Base
Classe, che definisce già per te gli accessi CRUD di base (Crea, Leggi, Aggiorna, Elimina). Questo è spiegato nel documento ufficiale qui Rails Model e qui Sovrascrivi accessor predefinito (scorri verso il basso fino al capitolo "Sovrascrivi accessor predefinito")
Supponiamo ad esempio che: abbiamo una tabella di database chiamata "utenti" che contiene tre colonne "nome", "cognome" e "ruolo":
Istruzioni SQL:
CREATE TABLE users (
firstname string,
lastname string
role string
);
Presumo che tu abbia impostato l'opzione config.active_record.whitelist_attributes = true
in config / environment / production.rb per proteggere la tua applicazione dall'exploit di assegnazione di massa. Questo è spiegato qui: Assegnazione di massa
Il tuo modello Rails funzionerà perfettamente con il modello qui sotto:
class User < ActiveRecord::Base
end
Tuttavia, sarà necessario aggiornare ogni attributo dell'utente separatamente nel controller affinché la vista del modulo funzioni:
def update
@user = User.find_by_id(params[:id])
@user.firstname = params[:user][:firstname]
@user.lastname = params[:user][:lastname]
if @user.save
# Use of I18 internationalization t method for the flash message
flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
end
respond_with(@user)
end
Ora, per semplificarti la vita, non vuoi creare un controller complicato per il tuo modello utente. Quindi utilizzerai il attr_accessible
metodo speciale nel tuo modello di classe:
class User < ActiveRecord::Base
attr_accessible :firstname, :lastname
end
Quindi puoi usare l '"autostrada" (assegnazione di massa) per aggiornare:
def update
@user = User.find_by_id(params[:id])
if @user.update_attributes(params[:user])
# Use of I18 internationlization t method for the flash message
flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
end
respond_with(@user)
end
Non hai aggiunto gli attributi "ruolo" attr_accessible
all'elenco perché non permetti ai tuoi utenti di impostare il loro ruolo da soli (come l'amministratore). Puoi farlo tu stesso su un'altra vista amministratore speciale.
Sebbene la vista dell'utente non mostri un campo "ruolo", un pirata potrebbe facilmente inviare una richiesta POST HTTP che includa "ruolo" nell'hash dei parametri. L'attributo "ruolo" mancante su attr_accessible
è per proteggere l'applicazione da quello.
Puoi comunque modificare l'attributo user.role da solo come di seguito, ma non con tutti gli attributi insieme.
@user.role = DEFAULT_ROLE
Perché diavolo dovresti usare il attr_accessor
?
Bene, questo sarebbe nel caso in cui il modulo utente mostri un campo che non esiste nella tabella degli utenti come colonna.
Ad esempio, supponiamo che la vista dell'utente mostri un campo "per favore, dì all'amministratore che sono qui". Non vuoi memorizzare queste informazioni nella tua tabella. Vuoi solo che Rails ti invii un'e-mail che ti avverta che un utente "pazzo" ;-) si è iscritto.
Per poter utilizzare queste informazioni è necessario memorizzarle temporaneamente da qualche parte. Cosa c'è di più facile che recuperarlo in un user.peekaboo
attributo?
Quindi aggiungi questo campo al tuo modello:
class User < ActiveRecord::Base
attr_accessible :firstname, :lastname
attr_accessor :peekaboo
end
Quindi sarai in grado di fare un uso user.peekaboo
consapevole dell'attributo da qualche parte nel tuo controller per inviare una e-mail o fare quello che vuoi.
ActiveRecord non salverà l'attributo "peekaboo" nella tabella quando lo fai user.save
perché non vede alcuna colonna corrispondente a questo nome nel suo modello.
attr_accessor
viene utilizzato per generare metodi getter e setter. Si prega di consultare la mia risposta a una domanda precedente per una spiegazione piuttosto esauriente diattr_accessible
: stackoverflow.com/questions/2652907/…, quindi aggiornare la domanda se sono necessari altri dettagli specifici successivamente.