2012-03-26 10 views
7

Chcę zmienić rekord, ale nie chcę go najpierw czytać z bazy danych, bo szczerze mówiąc nie widzę sensu. Jest ogromny i przez sieć jest powolny i drogi. Czy można to zrobić (łatwo)?Czy można zmienić rekord w szynach, bez wcześniejszego przeczytania?

Powiedzmy, że mam rekord z 100 polami (dla argumentów sake) i chcę zmienić jedno pole w tabeli. Mam naprawdę złe połączenie z bazą danych (jest to prawdą), ponieważ znajduje się na innym polu i nic nie mogę zrobić, aby to zmienić. Właśnie teraz ściągam rekord i szyny sprawdzają jego zawartość (ponieważ mam zserializowane bity), a następnie zmieniam jedno pole (jedną ze stu w zależności od warunku X) i ponownie zapiszę rekord. Przypuszczam, że ponownie zapisuję cały rekord w bazie danych, nie mając pojęcia, że ​​zmieniłem tylko jeden mały fragment. (ten ostatni bit jest założenie)

teraz, aby zmienić jeden rekord to wysyłanie ogromnej ilości danych przez sieć, a może okazać się, że jestem tylko zmienia jeden mały mała rzecz .. Także to robi dwa zapytania w bazie danych. Najpierw wybierz * następnie aktualizację ..

Moje pytanie ... czy istnieją mądrzejsze klasy bazowe, które robią to dobrze, aby pisać bez czytania?
Na początek mojej głowy sądziłbym, że dla każdego pola zmieniono metodę setera dla zmiany. Podczas zapisywania, chodzić po flagach i gdzie jest prawdziwe ... Czy to się teraz dzieje, jeśli tak, jak mogę z niego skorzystać?

+0

"(ten ostatni bit jest założeniem)" - to fałszywe założenie. ActiveRecord jest wystarczająco inteligentny, aby zapisywać tylko zmienione wartości. To już interally ma flagi, aby śledzić, które zmienione pola. –

+0

Właściwie, spójrz na dokumenty do tego (zwane "Partial Updates" btw) w rzeczywistości tylko w krawędziach i nie są planowane do wydania aż do Rails 4. Może istnieć wtyczka "częściowa aktualizacja" lub klejnot. –

+1

Tak, jest to inteligentna aktualizacja. A jeśli chodzi o znalezienie najpierw, jeśli wiesz, co chcesz zaktualizować, czy znalezienie rekordu z identyfikatorem nie jest stałą operacją czasową? jak duże może być DB? – Shaunak

Odpowiedz

6

Modele szyn mają metodę update, która wybiera SQL, a następnie aktualizację SQL.

Jego stosowanie jest proste (załóżmy, że masz model o nazwie Person)

Person.update(person_id, :user_name => 'New Name') 

Wadą jest to, że trzeba wiedzieć wcześniej osoby id.

Ale wtedy zawsze będziesz musiał wykonać zapytanie, aby się tego dowiedzieć. Możesz napisać własny kod SQL, aby zmienić wartość kolumny, z klauzulą ​​WHERE, która wyszukuje dany parametr.

Modele szyn mają metodę update_all, która wykonuje tylko aktualizację SQL bez ładowania danych. Nie polecam go jednak używać, ponieważ nie powoduje żadnych wywołań zwrotnych ani sprawdzeń poprawności posiadanego modelu.

Można użyć update_all tak:

Book.update_all "author = 'David'", "title LIKE '%Rails%'" 

PS: przykłady zostały zaczerpnięte z oficjalnej dokumentacji szyn. Jeśli szukasz aktualizacji lub update_all, znajdziesz obie metody w krótkim czasie.

Spójrz tam, to jest dobre miejsce, aby dowiedzieć się, co mogą zrobić szyny.

Rails API link

+0

Mogę napisać własny sql, ale dlaczego używać activerecord na wszystkich eh? Dzięki za to .. Nie jestem pewien jak stworzyć taki, który jest zawarty w moim modelu .. Mój widok i kontroler nie powinni wiedzieć, co się dzieje, tylko, że oszczędzają. – baash05

+0

Czasami trzeba pisać własne rzeczy, gdy masz bardzo specyficzne problemy, uwierz mi, hehe. Ale jeśli twoja strona nie jest czymś olbrzymim, z tysiącami dostępów na minutę, pobieranie tylko id z bazy danych jest w porządku, stosuj normalne metody i martw się tylko, jeśli naprawdę masz ku temu powód. Posłuchaj mądrych słów Knutha: "Przedwczesna optymalizacja jest źródłem wszelkiego zła". – Castilho

+0

Dzięki za aktualizację .. Mogę spróbować użyć go we wszystkich moich polach. Nie wiem jak jeszcze. – baash05

2

To nie jest oczywiste z dokumentacją, ale update_all jest odpowiedzią na to pytanie.

Book.where(id: 123).update_all(title: "War and Peace") 

wyniki w dokładnie jednym zapytaniu:

UPDATE `books` SET `books`.`title` = "War and Peace" WHERE `books`.`id` = 123 

Minęło trochę czasu odkąd to pytano, ale to tak dla Rails 4.

Powiązane problemy