2010-10-15 16 views
65

ho usato tecniche RESTful per generare un modello (in realtà, io sto usando Elaborare gemma, che lo fa per me), e ho aggiunto nuovi campi chiamati first_name e cognome al modello. La migrazione è andata bene. Ho aggiunto attr_accessor: first_name,: cognome al modello e mi aspettavo che sarebbe solo di lavoro. Ma quando cerco di massa assegnare nuovi casi con Doctor.create ({: first_name => "myname"}) ecc, sto ottenendo gli errori dicendo che non posso mass-assegnare gli attributi protetti."ATTENZIONE: Non può mass-assegnare protetta attributi"

ho pensato che il punto di utilizzare attr_accessor era quello di aggirare la protectedness dei campi di un modello. Puoi aiutarmi a dare un senso a questo messaggio?

Edit: Oh, e dal modo in cui i record non vengono creati sia. Ho pensato che dovrebbero essere poiché questo è solo un avvertimento, ma non sono nel database.

Edit2: qui è il mio modello

class Doctor < User 
    has_many :patients 
    has_many :prescriptions, :through=> :patients 

    validates_presence_of :invitations, :on => :create, :message => "can't be blank" 

    attr_accessor :invitations 
end 

e lo schema, che non ha il first_name e last_name perché sono creati nella tabella degli utenti, che è l'antenato dei medici. Ho usato l'ereditarietà di una tabella singola.

create_table :doctors do |t| 
    t.integer :invitations 

    t.timestamps 
end 

e questo è la migrazione per modificare la tabella degli utenti

add_column :users, :first_name, :string 
add_column :users, :last_name, :string 
add_column :users, :type, :string 

EDIT: Ecco il file seme. Non sto includendo il metodo truncate_db_table, ma funziona.

%w{doctors patients}.each do |m| 
    truncate_db_table(m) 
end 

Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName") 
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24") 
+0

Non sono ancora molto esperto su Rails 4, ma penso che questa domanda sia una domanda di Rails 3. La configurazione predefinita hardcoded in 'config/application.rb' in Rails 4 è vuota! –

+0

http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class – shilovk

risposta

139

Non confondere attr_accessor con attr_accessible. Accessor è incorporato in Ruby e definisce un metodo getter - model_instance.foo # returns something - e un metodo setter - model_instance.foo = 'bar'.

Accessibile definito da Rails e rende l'attributo di massa assegnabile (fa il contrario di attr_protected).

Se first_name è un campo nella tabella del database del modello, quindi Rails ha già definito getter e setter per tale attributo. Tutto quello che devi fare è aggiungere attr_accessible :first_name.

+0

Ora ricevo l'errore "attributo sconosciuto" sugli inviti quando rastrello il file seme. So che ho questo campo nel database, però; è nel file di migrazione ... – picardo

+0

È nel file di migrazione, ma hai eseguito le migrazioni? Pubblica il tuo file di semi. –

+0

Hai aggiornato le altre cose? Hai ancora attr_accessor nel tuo modello, anche se è sbagliato. –

1

Non utilizzare attr_accessor qui. ActiveRecord crea quelli automaticamente sul modello. Inoltre, ActiveRecord non creerà un record se è gettato un errore di convalida o di massa-assegnazione.

MODIFICA: non è necessaria una tabella medici, è necessaria una tabella utenti con una colonna di tipo per gestire Rails Single Table Inheritance. Gli inviti saranno sulla tabella degli utenti. Ah, vedo nel tuo esempio di codice aggiunto che hai tipo sugli utenti. Sbarazzati della tabella dei medici, sposta gli inviti agli utenti e penso che dovresti essere ok. Inoltre sbarazzarsi del attr_accessor. Non necessario.

Ricordare che le barre STI utilizza la stessa tabella per tutte le classi e sottoclassi di un particolare modello. Tutti i record del medico saranno righe nella tabella utenti con un tipo di 'medico'

MODIFICA: Inoltre, sei sicuro di voler solo convalidare la presenza di inviti alla creazione e non gli aggiornamenti?

+0

Quando non lo uso, però, Rails mi dice "metodo non trovato" mentre sto rastrellando il file seme. Cosa dovrei fare in quel caso? – picardo

+0

Puoi pubblicare il tuo codice modello e il rake? Anche la migrazione che ha creato il modello. Assicurati che quelle colonne siano state create nel db. –

11

di incidere il vostro app insieme in un modo insicuro totalmente inadatti al modo di produzione:

Vai a/config/dell'applicazione.rb Scorri verso il basso verso la fine dove troverai

{config.active_record.whitelist_attributes = true} 

Impostarlo su falso.

EDIT/BTW (dopo 4 mesi di lavoro rubino intenso tra cui un laboratorio di 11 settimane): DHH ritiene che, per noobies (parole sue), "Up and Running" è più importante che "molto sicuro" .

ESSERE CONSIGLIATO: Anche se questa risposta (il mio primissimo stackoverflow credo) è ora a +6, è stata pari a -4 nella sua storia, il significato di ciò è che molti sviluppatori esperti di rail hanno sentito molto appassionato di non che desidera che tu faccia questo.

UPDATE: 3 anni più tardi, un altro modo per fare questo - ancora una volta, non è sicuro, ma migliore rispetto alla soluzione di cui sopra, probabilmente perché devi farlo per ogni modello

class ModelName < ActiveRecord::Base 
    column_names.each do |col| 
    attr_accessible col.to_sym 
    end 
    ... 
end 
+32

Questo è davvero un pessimo consiglio anche con l'avvertimento di "precoce codifica". Quando mai gli sviluppatori hanno la possibilità di tornare indietro e rifattorizzare la loro intera app? Fallo bene fin dall'inizio. – toxaq

+4

"ricorda che questo è un buco di sicurezza ma puoi affrontarlo più tardi" Quando avevi intenzione di affrontarlo? Più tardi, quando è in produzione? Ho appena aggiunto "qual è la tua opinione su attr_accessible?" alla mia lista di domande di intervista. – toxaq

+0

Posso suggerire una modifica per chiarire la tua risposta? Dal tuo post, non è completamente chiaro che il valore predefinito è il modo più sicuro, e cambiandolo a false fornisce un facile accesso agli attributi del modello, ma apre la brutta falla di sicurezza. – Excalibur

0

Aggiungi alla tua attr_accessible : variable1, variable2 file di percorso della tabella.

0

Accetto con la risposta di @Robert Speicher Ma raccomando vivamente di utilizzare Strong parameter anziché attr_accessible per proteggere dall'assegnazione di massa.

Cheers!

Problemi correlati