2010-10-15 4 views
65

Ich habe RESTful Techniken verwendet, um ein Modell zu generieren (tatsächlich verwende ich Devise gem, was das für mich tut), und ich habe neue Felder namens first_name und hinzugefügt Nachname zu dem Modell Migration ging gut. Ich habe attr_accessor: first_name,: last_name zum Modell hinzugefügt und erwartet, dass es einfach funktioniert. Aber wenn ich versuche, neue Instanzen mit Doctor.create ({: first_name => "MeinName"}) usw. massenweise zuzuweisen, bekomme ich Fehler, die sagen, dass ich geschützte Attribute nicht massenweise zuweisen kann."WARNUNG: Kann keine geschützten Attribute zuweisen"

Ich dachte der ganze Sinn der Verwendung von attr_accessor war, um die Schutzwürdigkeit der Felder eines Modells zu umgehen. Kannst du mir helfen, diese Botschaft zu verstehen?

Edit: oh, und übrigens die Datensätze werden auch nicht erstellt. Ich dachte, sie sollten sein, da dies nur eine Warnung ist, aber sie sind nicht in der Datenbank.

Edit2: hier ist mein Modell

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 

und das Schema, die nicht den first_name und last_name haben, weil sie in der Benutzer-Tabelle erstellt werden, die die Vorfahren der Ärzte sind. Ich habe die Vererbung einzelner Tabellen verwendet.

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

    t.timestamps 
end 

und dies ist die Migration der Benutzer-Tabelle

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

EDIT zu ändern: hier ist die Seed-Datei. Ich schließe die truncate_db_table-Methode nicht ein, aber sie funktioniert.

%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

Ich bin noch nicht sehr klug auf Rails 4, aber ich denke, diese Frage ist eine Rails 3 Frage. Die voreingestellte hardcodierte Konfiguration in 'config/application.rb' in Rails 4 ist leer! –

+0

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

Antwort

139

Nicht verwechseln attr_accessor mit attr_accessible. Accessor ist in Ruby integriert und definiert eine Getter-Methode - model_instance.foo # returns something - und eine Setter-Methode - model_instance.foo = 'bar'.

Accessible wird durch Rails definiert und macht das Attribut massenzuweisbar (macht das Gegenteil von attr_protected).

Wenn first_name ein Feld in der Datenbanktabelle Ihres Modells ist, dann hat Rails bereits Getter und Setter für dieses Attribut definiert. Alles, was Sie tun müssen, ist attr_accessible :first_name hinzuzufügen.

+0

Jetzt bekomme ich "unbekanntes Attribut" Fehler auf Einladungen, wenn ich die Seed-Datei hake. Ich weiß, dass ich dieses Feld in der Datenbank habe, obwohl; Es ist in der Migrationsdatei ... – picardo

+0

Es ist in der Migrationsdatei, aber haben Sie die Migrationen ausgeführt? Veröffentlichen Sie Ihre Seeds-Datei. –

+0

Hast du die anderen Sachen aktualisiert? Sie haben immer noch attr_accessor in Ihrem Modell, obwohl das falsch ist. –

1

Sie attr_accessor hier nicht verwenden. ActiveRecord erstellt diese automatisch im Modell. Außerdem wird ActiveRecord keinen Datensatz erstellen, wenn ein Fehler bei der Validierung oder Massenzuordnung ausgelöst wird.

BEARBEITEN: Sie benötigen keine Ärzte-Tabelle, Sie benötigen eine Benutzer-Tabelle mit einer Spalte Typ, um Schienen Single Table Inheritance zu behandeln. Die Einladungen werden auf der Benutzertabelle angezeigt. Ah, ich sehe in Ihrem zusätzlichen Codebeispiel, dass Sie Benutzer eingeben. Entfernen Sie den Arzttisch, verschieben Sie Einladungen an die Benutzer, und ich denke, Sie sollten in Ordnung sein. Entferne auch den attr_accessor. Nicht benötigt.

Denken Sie daran, dass STI für alle Klassen und Unterklassen eines bestimmten Modells dieselbe Tabelle verwendet. Alle Ihre Doctor-Datensätze werden Zeilen in der Tabelle Benutzer mit einer Art von "Arzt"

EDIT: Sind Sie sicher, dass Sie nur die Anwesenheit von Einladungen bei der Erstellung und nicht Updates überprüfen möchten?

+0

Wenn ich es nicht verwende, sagt Rails mir jedoch "Methode nicht gefunden", da ich die Seed-Datei hake. Was soll ich in diesem Fall tun? – picardo

+0

Können Sie Ihren Modellcode und Ihre Rake-Aufgabe posten? Auch die Migration, die das Modell erstellt hat. Stellen Sie sicher, dass diese Spalten in der Datenbank erstellt werden. –

11

Um Ihre App zusammen in einer unsicheren Art und Weise völlig ungeeignet für den Produktionsmodus Hack:

Zur/config/application.rb Scrolle nach unten zum Ende, wo du findest

{config.active_record.whitelist_attributes = true} 

Setze es auf false. btw

EDIT/(nach 4 Monaten rubin intensiver Arbeit mit einem 11 Wochen Workshop): DHH glaubt, dass für noobies (seine Worte), "up and running" ist wichtiger als "sehr sicher" .

BEACHTEN SIE: Obwohl diese Antwort (meine allererste auf stackoverflow ich denke) ist jetzt bei +6, es war so niedrig wie -4 in seiner Geschichte, die Bedeutung dieser eine Menge erfahrene Rails Entwickler fühlte sich sehr leidenschaftlich über nicht wollen Sie dies tun.

UPDATE: 3 Jahre später, eine andere Art und Weise, dies zu tun - auch hier nicht sicher, aber besser als die obige Lösung wahrscheinlich, weil Sie es für jedes Modell

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

Das ist wirklich ein schlechter Rat, sogar mit dem Vorbehalt der "frühen Codierung". Wann bekommen Entwickler jemals die Chance, ihre gesamte App neu zu gestalten? Mach es von Anfang an richtig. – toxaq

+4

"bedenken Sie, dass dies ein Sicherheitsloch ist, aber Sie können später damit umgehen" Wann haben Sie geplant, damit umzugehen? Später, wenn es in Produktion ist? Ich habe gerade hinzugefügt "Was ist deine Meinung zu attr_accessible?" zu meiner Liste von Interviewfragen. – toxaq

+0

Kann ich eine Änderung vorschlagen, um Ihre Antwort zu klären? Aus Ihrem Post ist nicht ganz klar, dass der Standardwert der sicherere Weg ist, und wenn Sie ihn in false ändern, erhalten Sie einfachen Zugriff auf Modellattribute, aber er öffnet das schlechte Sicherheitsloch. – Excalibur

0

hinzufügen attr_accessible : variable1, variable2 zu Ihrem zu tun haben Tabelle Routendatei.

0

Stimmen Sie mit @Robert Speicher Antwort zu Aber ich werde dringend empfehlen, dass Sie Strong parameter anstelle von attr_accessible verwenden, um vor Massenausrichtung zu schützen.

Prost!

Verwandte Themen