2010-10-15 31 views
65

Użyłem technik RESTful do wygenerowania modelu (w rzeczywistości używam Devise gem, co robi to dla mnie), i dodałem nowe pola o nazwie first_name i last_name do modelu. Migracja poszła dobrze. Dodałem attr_accessor: first_name,: last_name do modelu i oczekiwałem, że po prostu zadziała. Ale kiedy próbuję masowo przypisać nowe wystąpienia za pomocą Doctor.create ({: first_name => "MyName"}) itp., Dostaję błędy mówiąc, że nie mogę masowo przypisywać chronionych atrybutów."OSTRZEŻENIE: Nie można masowo przypisywać chronionych atrybutów"

Uważam, że cały sens korzystania z attr_accessor było obejście ochrony pól modelu. Czy możesz mi pomóc zrozumieć tę wiadomość?

Edycja: oh, a przy okazji także rekordy nie są tworzone. Myślałem, że powinny być, ponieważ to tylko ostrzeżenie, ale nie ma ich w bazie danych.

Edit2: tu jest mój model

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 

i schemat, który nie ma first_name i last_name ponieważ są one tworzone w tabeli użytkowników, który jest przodkiem lekarzy. Użyłem dziedziczenia pojedynczego stołu.

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

    t.timestamps 
end 

i to jest migracja do zmiany tabeli użytkowników

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

EDIT: tutaj jest plik nasion. Nie włączam metody truncate_db_table, ale działa.

%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

Nie jestem bardzo doświadczony w Railsach 4, ale myślę, że to pytanie jest zadaniem Rails 3. Domyślna konfiguracja na twardym dysku w 'config/application.rb' w Rails 4 jest pusta! –

+0

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

Odpowiedz

139

Nie mylić attr_accessor z attr_accessible. Accessor jest wbudowany w Ruby i definiuje metodę pobierającą - model_instance.foo # returns something - oraz metodę ustawiającą - model_instance.foo = 'bar'.

Dostęp jest definiowany przez Railsy i powoduje, że atrybut jest przypisywany masowo (przeciwnie niż attr_protected).

Jeśli first_name jest polem w tabeli bazy danych modelu, to Railsy już zdefiniowały obiekty pobierające i ustawiające dla tego atrybutu. Wszystko, co musisz zrobić, to dodać attr_accessible :first_name.

+0

Teraz otrzymuję komunikat "nieznany atrybut" podczas zaproszeń, gdy zgrywam plik źródłowy. Wiem, że mam to pole w bazie danych; jest w pliku migracji ... – picardo

+0

Jest w pliku migracji, ale czy uruchomiłeś migracje? Opublikuj plik z nasionami. –

+0

Czy zaktualizowałeś inne rzeczy? Nadal masz attr_accessor w swoim modelu, mimo że to źle. –

1

Nie używaj tutaj attr_accessor. ActiveRecord tworzy je automatycznie na modelu. Ponadto, ActiveRecord nie utworzy rekordu, jeśli zgłoszony zostanie błąd sprawdzania poprawności lub przypisania masy.

EDYCJA: Nie potrzebujesz tabeli lekarzy, potrzebujesz tabeli użytkowników z kolumną typu do obsługi Railsów Single Table Inheritance. Zaproszenia będą w tabeli użytkowników. Ach, widzę w twoim dodanym przykładowym kodzie, że masz typ na użytkownikach. Pozbądź się tabeli lekarzy, przenieś zaproszenia do użytkowników i myślę, że powinieneś być w porządku. Pozbądź się także attr_accessor. Nie są potrzebne.

Należy pamiętać, że STI korzysta z tej samej tabeli dla wszystkich klas i podklas określonego modelu. Wszystkie rekordy lekarza będą wiersze w tabeli użytkowników z typem "lekarza"

EDYCJA: Czy na pewno chcesz potwierdzić obecność zaproszeń przy tworzeniu, a nie aktualizacje?

+0

Kiedy go nie używam, Railsy mówią mi, że "nie znaleziono metody", ponieważ zgrabiam plik źródłowy. Co powinienem zrobić w takim przypadku? – picardo

+0

Czy możesz zamieścić swój kod modelu i zadanie rake? Także migracja, która stworzyła model. Upewnij się, że kolumny zostały utworzone w bazie danych. –

11

włamać swoją aplikację razem w niebezpieczny sposób całkowicie nienadające się do trybie produkcyjnym:

do/config/aplikacji.rb Przewiń w dół do końca, gdzie znajdziesz:

{config.active_record.whitelist_attributes = true} 

Ustaw na false.

EDIT/btw (po 4 miesiącach ruby-intensywnej pracy w tym warsztacie 11 tygodniu): DHH uważa, że ​​dla Noobies (jego słowa), „gotowy do pracy” jest ważniejsze niż „bardzo bezpieczna” .

ZOSTAĆ ZADOWOLONY: Chociaż ta odpowiedź (mój pierwszy na stackoverflow, jak sądzę) jest teraz na +6, to było tak niskie, jak -4 w swojej historii, znaczenie tego było dużo doświadczonych deweloperów szyny czuł namiętny o nie chcąc, abyś to zrobił.

UPDATE: 3 lata później inny sposób to zrobić - ponownie, nie jest bezpieczne, ale lepsze niż powyższego roztworu prawdopodobnie dlatego, że trzeba to zrobić dla każdego modelu

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

To naprawdę zła rada, nawet z zastrzeżeniem "wczesnego kodowania". Kiedy programiści mają szansę na powrót i refaktoryzację całej aplikacji? Zrób to poprawnie od samego początku. – toxaq

+4

"pamiętaj, że jest to luka w zabezpieczeniach, ale możesz sobie z tym poradzić później" Kiedy planowałeś sobie z tym poradzić? Później, kiedy jest w produkcji? Właśnie dodałem "jaka jest Twoja opinia na temat attr_accessible?" na moją listę pytań do rozmowy kwalifikacyjnej. – toxaq

+0

Czy mogę zaproponować zmianę w celu wyjaśnienia Twojej odpowiedzi? Ze swojego wpisu nie jest całkowicie jasne, że domyślna wartość jest bezpieczniejsza, a zmiana na wartość false daje łatwy dostęp do atrybutów modelu, ale otwiera złą lukę w zabezpieczeniach. – Excalibur

0

Dodaj do listy attr_accessible : variable1, variable2 plik trasy tabeli.

0

Zgadzam się z odpowiedzią @Robert Speicher Ale zdecydowanie zalecam użycie Strong parameter zamiast attr_accessible w celu ochrony przed wyrównaniem masy.

Pozdrawiam!

Powiązane problemy