2011-05-30 21 views
7

Obecnie zacząłem uczyć się frameworku Ruby i Ruby on Rails. Odkryłam, że w tabeli records mogę znaleźć zapis o ID 5 i usunąć go za pomocą następującego kodu:Dlaczego nie mogę używać Record.all.destroy w Railsach?

Record.find(5).destroy

To sprawia, że ​​metody łańcucha I sense- celu znalezienia rekordu i zniszcz to. Jednakże, jeśli chcę, aby zniszczyć wszystkie rekordy w tabeli, polecenie logiczne byłoby dodaje, jako selektor all wybiera wszystkie rekordy w tabeli:

Record.all.destroy

I to zwraca NoMethodError! Jestem świadomy, że mogę użyć Record.destroy_all lub Record.delete_all do wykonania tego zadania, jednak chciałbym wiedzieć, dlaczego nie mogę po prostu użyć najbardziej logicznego wyboru, zamiast szukać rzeczy takich jak delete_all. Jestem nowicjuszem w tej dziedzinie, więc jest całkowicie możliwe, że brakuje tu czegoś fundamentalnego.

Dzięki za wszelkie odpowiedzi z góry.

+0

istotnie dobre pytanie, bo najpierw wypróbowałem to samo ... Można użyć 'Record.all.each {| r | r.destroy} 'oczywiście, ale to nie jest tak logiczne jak' Record.all.destroy' –

Odpowiedz

14

To była decyzja projektowa. DataMapper przejął your approach. Zmuszenie do napisania wyraźnego zapisu destroy_all może być uciążliwe, ale uniemożliwi ci robienie czegoś, czego naprawdę nie chcesz (np. Usunąć wszystko z tabeli, np. x = User; ...; x.destroy).

+0

Dzięki - to była odpowiedź, której szukam. Sądzę, że może to być dobra ochrona przed niezamierzonymi masowymi kasacjami rekordów. – element119

3

Zgadzam się, że będzie to możliwe w przypadku logicznego. Technicznie rzecz biorąc, Record.all zwraca kolekcję (lub proxy do kolekcji), która nie implementuje metody destroy.

1

Kiedy masz

Record.find(5) 

ten zwraca rekord obiektu/instancję, która reprezentuje dane w wierszu w tabeli. Następnie wywołujesz metodę #destroy na tym obiekcie, który jest zdefiniowany przez twój model Record.

Kiedy masz

Record.all 

ta zwraca obiekt Array. Abyś wtedy zadzwonił na #destroy na tablicy, musiałbyś przerobić klasę rdzeniową Ruby na rdzeń Array, aby mieć metodę #destroy.

+0

tak i nie ... Ze względu na dynamiczny charakter ruby, same szyny * mogą * wstawiać niszczące akcje na tablicach rekordów, bez małpowania wszystkich obiektów tablicy ... ale jest to decyzja projektowa, aby nie, myślę, że myślę. – DGM

1

Najprostszym sposobem, aby uniknąć Record.destroy_all byłby Record.all.each {|r| r.destroy}. Może to nieco zaspokoić preferencje dotyczące projektowania interfejsu API, ale powinno być znacznie wolniejsze niż pierwsza opcja.

0

Właściwie możesz (w pewnym sensie). Ponieważ .all zwraca tablicę, a nie aktywną relację rekordów, co dokładnie byś usunął? Nie powiedziałbym, że Record.all.destroy jest w ogóle logiczny - czy usuwasz obiekt tablicy?

Jedną z rzeczy, którą można zrobić, jest mapowanie wynikowej tablicy, a ponieważ map akceptuje proc (&), można wykonać ten proces dla każdego obiektu w tablicy.

Record.all.map(&:destroy) 

Uwaga, spowoduje to wywołanie zwrotne wszystkich obiektów, które mogą być wolniejsze niż zamierzano. Jeśli chcesz uniknąć wyzwalania zwrotnego, możesz zamiast tego zniszczyć odpowiednią metodę destrukcyjną.(Podpowiedź:: usuwanie)

Alternatywnie, można po prostu zrobić:

Record.destroy_all or Record.delete_all 

jak stwierdził w swoim pytaniu.

Powiązane problemy