Ponieważ kilka moich modeli jest bardzo podobnych, są to róznego rodzaju komentarze, które różnią się od siebie tym, co komentują. Chciałem je sobie uogólnić i w tym celu nadpisałem ActiveRecord::Base - pod linkiem http://pastie.caboo.se/196277 jest kod. U góry “nadpis”, a niżej model który z niego korzysta.
Pojawia się problem tego typu, ze w klasie AR::Base nie znane są jeszcze metody modelu wynikające z pól tablicy bazy danych, w związku z czym mam missing method error w walidacji dla ‘author_id’. Kwestia jest tego typu, jak mam to ugryźć, aby walidacja mogła być przeprowadzana w tym “uogólnieniu”?
Walidacja to na pewno nie jest tutaj przyczyną błędu. Problemem jest tu przede wszystkim sposób w jaki probujesz to rozwiązać.
Jeśli chcesz faktycznie mieć taki model bazowy to zrób sobie klasę, z której będziesz dziedziczyć, a nie mieszaj tak w ActiveRecord::Base.
class CommentBase < ActiveRecord::Base
self.abstract_class = true
end
Potem możesz dziedziczyć po tej klasie.
Jak dla mnie to przypadek dla ‘polimoprhic association’: http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations
Zgadza się, też o tym pomyślałem, ale nie chciałem już “mącić”. Jednak to będzie lepsze rozwiązanie.
po pierwsze nie powinineś nadpisywać AR::Base, o wiele lepiej odziedziczyć ogólny model i z niego dziedziczyć poszczególne.
Dodatkowo, dlaczego nie wykorzystasz polimorfizmu, i nie użyjesz jednej tabeli z komentarzami?
ogólnie twoje rozwiązanie ale troszke bardziej eleganckie:
nadal proponuje użyć polimorfizmu, i zapoznać sie lepiej z ruby, metoda validate jest już wywoływana w momencie kiedy te pola istnieją, więc to inne błędy powodują nie działanie tego kodu
Dzięki Panowie za posty, sporo mi rozjaśniły. Miałem początkowo zamiar zrobić jedną tabelę z komentarzami, ale nie bardzo wiedziałem jak przypisać je do odpowiednich, komentowanych modeli. Teraz, dzięki Waszej pomocy już wiem i zrobię to za pomocą jednej tabeli i polimorfizmu.
Po zostaje dla mnie jeszcze jedna kwestia, w której potrzebuję drobnego wyjaśnienia. Czy w kontrolerze komentarzy warto robić oddzielne akcję dla każdego typu komantarza, czy może lepiej określać typ komentowanego modelu za pomocą parametru?
pozdrawiam,
Piotr
Wykrzycz sie!
EDIT: Już sobie poradziłem. To świetna rzecz, dużo mnie pisania, tworzenia widoków i większy porządek. Jeszcze raz dzięki za powyższe posty
Odświeżam temat, bo znów mam pewien problem z uogólnianiem modelu. Tym razem sytuacja jest taka, że kilka metodeli ma pare identycznych relacji i co za tym idzie kilkanaście takich samych metod obsługujących te relacje. Aby było wszystko ładnie i pięknie, postanowiłem utworzyć klasę abstrakcyjną, po której będą te modele dziedziczyć. Jeśli chodzi o metody, to wszystko śmiga ładnie. Jednak nie mogę w tej chwili, w klasie abstrakcyjnej zadeklarować relacji, bo wyskakują błędy nie istnienia metod odnoszących się do pól z modelu z którym tworzymy relacje.Jest jakiś sposób aby wrzucić relacje do tego uogólnienia, czy trzeba będzie powtarzać je w każdym z modeli?
Poszukaj jakiegoś pluginu acts_as_* i pooglądaj źródła. Tam z reguły jest definicja tej metody acts_as_*, która do klasy, w której została wywołana, dodaje różne ciekawe rzeczy (na przykład właśnie asocjacje) itp. itd.
Wiem, że z początku może to wyglądać na zawiłe, ale jeżeli to zrozumiesz i będziesz umiał używać, to automatycznie zyskujesz bardzo fajne narzędzie do wypakowywania z aplikacji powtarzających się wzorów i wrzucania ich do pluginów (nawet jeżeli nie są to pluginy, możesz to równie dobrze wrzucić do lib/).
Jeżeli ktoś ma więcej czasu niż ja, to może będzie tak dobry i Ci wytłumaczy o co chodzi Ale najlepiej spróbuj sam, nie ma to jak obczaić jakieś coś czytając kod
Patrze po tych acts_as różnych i nie wiem na co mam patrzeć. Zazwyczaj jadą normalnie has_many czy belongs_to bez jakiś dziwów. Z tą różnicą że tam jest jazda na modułach, a ja mam klasę abstrakcyjną. Potrzebuje jakiś wskazówek żeby to rozkminić
drogus możesz rzucić jakąś podpowiedź, bo się z tym męczę już ponad tydzień?
Najprościej zacząć od starutkiego (ale wciąż działającego) pluginu acts_as_tree – jak zrozumiesz jego kod (a jeśli nie rozumiesz, musisz się podciągnąć w Rubym), zrozumiesz o co chodziło Drogusowi
Okej, napisałem sobie taki plik:
[code]module ActiveRecord
module SpecialModel
module ClassMethods
def special_model
has_many :comments, :as => :commentable
has_many :ranks, :as => :rankable # dzieło ma oceny, w których zostało ocenione
has_many :favorites, :as => :favoritable
class_eval <<-EOV
include ActiveRecord::SpecialModel::InstanceMethods
EOV
end
end
module InstanceMethods
def add_view
#metoda zwiększająca o 1 liczbę wyświetleń obiektu
self.stat.update_attribute('views', self.stat.views + 1)
end
end
end
end[/code]
wrzuciłem go do lib i dałem require w environment.rb. Chciałem zobaczyć jak działa, ale jakoś źle go wrzuciłem bo mam komunikat:
gdy w modelu wywołuje metoda special_model. Gdzie i jak to powinienem wrzucić, aby było poprawnie?
Musisz odzwierciedlić hierarchię przestrzeni nazw w katalogach na dysku, tj.:
RAILS_ROOT/lib/active_record/special_model.rb
Jeśli chcesz go wrzucić bezpośrednio do RAILS_ROOT/lib, to nie umieszczaj go w przestrzeni ActiveRecord.
[quote=Piotr Misiurek]Chciałem zobaczyć jak działa, ale jakoś źle go wrzuciłem bo mam komunikat:
undefined local variable or method `special_model' for #<Class:0xb70e0634>
[/quote]
Powinieneś jeszcze dołączyć stworzony moduł do modelu:
class Something < ActiveRecord::Base
extend SpecialModel::ClassMethods
end
Dzięki wszystkim za pomoc, już skumałem co i jak, i wszystko wydaje się ładnie biegać. Wielki dzięki