Cześć,
Zaczynam zabawe z asocjacjami polimorficznymi, oto jej skutki: http://pastie.org/389138
Chodzi o to że mam na stronie filmy i zdjęcia które można dodawać do “ulubionych”, chcę by ficzer ten obsłużył jeden kontroler. To co napisałem działa, jednak myślę że nie jest to najlepsze rozwiązanie mojego problemu. Proszę was o wskazówki jak powinienem to wszystko napisać. Z góry dziękuje za wszystkie porady.
Hej,
ja bym nie definiował metod fav i unfav, tylko użył REST-a, wtedy masz new oraz destroy, których możesz użyć.
Myślę, ze możesz zdefiniować w modelu metody add_to_favorites i remove_from_favorites. Twój kod w kontrolerze jest dość długi. No i mając wszystko w modelu możesz napisać łatwo testy, więc masz pewność, że Ci wszystko działa.
Ale co do pluginów, to są osoby, które twierdzą, że używanie do wszystkiego pluginów nie jest właściwe. No i czasem pluginy potrafią robić zamieszanie i problemy.
Polecaliście mi na forum użycie rest, zrobienie akcji create i destroy. Tak też uczyniłem, ale nie wiem co dalej ;), oto efekt: http://pastie.org/389836
Zostaw na razie REST w spokoju, Sławosz dał Ci radę typu “jak nie działa Ci samochód, zmień drzwi do piwnicy”. Jedna rzecz na raz - skoro uczysz się obsługi modeli i polimorficznych asocjacji, to na tym się skup. Oldschoolowe :action, :controller naprawdę nie jest złe, a RESTa zdążysz się nauczyć przy innej okazji.
Nie podałeś kodu zamieszanych modeli, ale zakładam że jest właściwy.
Dalsze punkty dotyczą odchudzania FavoritesController:
Określanie typu faworytki: kod z linijek 8-11 możesz zamienić na: @type = Kernel.const_get(params[:type].capitalize).find(params[:id])
1a) koniecznie poczytaj co robi Kernel.const_get i nawet nie myśl o zamianie tego na eval()
1b) poczytaj o polymorphic routes, podobnie a bardziej elegancko
funkcjonalność linijek 13-19 wywal do modelu tak, żeby można było zrobić
flash[:notice] = current_user.add_or_remove_favorite(@type)
To tylko przykład refaktoryzacji; w każdym razie odchudzamy kontroler i uelastyczniamy kod aplikacji, rajt?
nie podoba mi się idea ładowania funkcjonalności zarówno dodawnania, jak i usuwania faworytki do tej samej metody kontrolera; takie decyzje powinny być podejmowane / podsuwane użytkownikowi na podstawie widoku, a jeśli “chakiersko” podmieni ścieżkę, niech się po prostu nic nie dzieje
linijka 10 “else break” - no prośba
4a) find i tak rzuci wyjątkiem jeśli nie znajdzie danego elementu - oczywiście gdzieś (ApplicationController) przechwytujesz (rescue) wyjątek ActiveRecord::RecordNotFound i wyświetlasz stronę typu “nie znaleziono elementu”, prawda?
4b) Kernel.const_get też wypluje wyjątek jeśli nie znajdzie stałej (w tym przypadku klasy) o podanej w params[:type] nazwie
4c) zawsze możesz (tu nawet powinieneś) po prostu zrobić pod koniec akcji/metody (przed end zamykającym definicję metody)
rescue
render :text => “wystąpił błąd przy dodawaniu faworytki”
W niektórych aplikacjach widać dziwną tendencję do łączenia 2 akcji w jedną, na przykład zamiast new i create jest tylko new, która w zależności od tego czy to get czy post działa jak new albo create. Czasami widzę pójście nawet dalej - akcje new i edit są łączone.
Ja rozumiem, że niektórym może się wydawać, że zrobienie z 4 metod jednej może uprościć kod, ale to jest myślenie całkowicie błędne. Po pierwsze ciężko jest wtedy zrobić specyficzne dla każdej akcji respond_to, dużo ciężej jest debugować, kod jest tak naprawdę bardziej zawiły, bo dochodzi trochę ifów i niestandardowych zachować. Strasznie tego nie lubię.
Szczególnie, że jak podchodzę do czyjejś aplikacji, to nie znam kodu i zamiast mieć coś co jest standardem dostaję jakieś widzimisię programisty, który uważa, że to jest niesamowicie przebiegłe, że wszystko upchnął do jednej metody.
Polecam przy okazji prezentację Marcela Moliny - Beautiflu code (albo coś w tym stylu), w której pokazuje kawałek swojego kodu, który może się z początku wydawać sprytnie napisany, ale po przeanalizowaniu wychodzi na to, że tak naprawdę zamiast jakieś dziwnej struktury wystarczy zastosować jednego switcha, który zrobi to o wiele szybciej, wydajniej i nawet początkujący zrozumie o co chodzi.