Problem z obsługą self.method_missing

Mam dwa modele User i User2 < ActiveRecord::Base na modelu User wywołuje np. methodę find czyli User.find niestety model User nie ma self.find ale chce zrobić tak, że gdy nie ma takiej metody w User to wywoła ją z User2. Kod z którym nie mogę sobie poradzić jest tutaj: https://github.com/wafcio/multi_mapper/commit/6fa44b0ca8d586fbaf877114e4f89df7783acded . Myślałem że to naprawia błąd, ale niestety dalej mam komunikat:

SystemStackError: stack level too deep from .../lib/ruby/1.9.1/irb/workspace.rb:80 Maybe IRB bug!

To wszystko śmierdzi z daleka.

Czy masz jakiś powód aby nie stosować zwykłego dziedziczenia?

class User < User2

@qertoip: to jest rozwiązanie dla obsługi wielu mapperów w jednej aplikacji. Mi np. devise zaczyna śmierdzieć coraz bardziej, bo już na poziomie routingu łączy się z modelem, ale kto co lubi, jeśli masz pomysł na to żeby inaczej to rozwiązać to daj przykład

@RawOnRails: Nie może być dziedziczenie, bo User2 dziedziczy po ActiveRecord, czyli to jest mapper, ten gem może przełączać mappery dlatego może mieć też User3 (z MongoMapperem) itp.

Hmm. Ciekaw jestem czy zadziała tutaj

delegate

Zerknąłem na Twojego Githuba i Readme. Czy dobrze rozumiem, że chcesz oddzielić logikę aplikacji od warstwy bazodanowej aby móc podłączyć różne “backendy”?

Całkowitym zbiegiem okoliczności tak się składa, że również nad tym pracuję: https://github.com/qertoip/guru_watch/

W moim raczkującym przykładzie logika aplikacji jest w przypadkach użycia (app/use_cases) i encjach (app/entities). Ta logika jest całkowicie wyizolowana od ActiveRecorda (zgodnie z postulatami Trygve Reenskaug, Ivara Jacobsona, Roberta Martina, Avdi Grimma i innych).

Dalej, można podłączyć jeden z dwóch backendów: ActiveRecord (produkcja i testy integracyjne) lub ActiveMemory (testy jednostkowe i funkcjonalne).

To jest bardzo wczesny etap eksperymentu ale widać już całą architekturę i jest to uruchamialne.

@Hitsu: delegate działa za bardzo statycznie

@qertoip: odnose się do twojej aplikacji: 0 dokumentacji -> tylko autor wie jak to użyć, uses_case, entities -> to jest inżynieria oprogramowania czy programowanie ? jak napiszesz jak to się używa to może zaczerpnę pewne pomysły z tego ale teraz głównie chodzi mi o rozwiązanie problemu z self.method_missing, co dziwniejsze, jesli model ma na sztywno zakodowaną tą funkcję to nie krzyczy że jest jakiś błąd.

To jest celowe. Więcej: to jeden z głównych postulatów. Przypadki użycia są centralne dla architektury aplikacji. Są na wierzchu aby intencja aplikacji była łatwa do odczytania.

Po pomysły (koncepcje) najlepiej sięgnąć do materiałów źródłowych. Moja aplikacja to tylko eksperyment jak to zrealizować w praktyce (i czy warto?). To nie jest narzędzie czy biblioteka “do użycia”, tylko przykład i punkt wyjścia do dyskusji o takiej architekturze aplikacji. Oczywiście będzie więcej dokumentacji na późniejszym etapie. Dzięki za zerknięcie.

Famous last words :wink:

Oraz od dłuższego czasu jestem fanem:
http://tom.preston-werner.com/2010/08/23/readme-driven-development.html

(albo: dokumentacja jako warstwa jeszcze wyżej od testów akceptacyjnych)

Tomash w pełni ciebie popiera i również jestem tego zwolennikiem, bo jak ktoś nowy wchodzi do jakiegokolwiek projektu, bo ciężko mu się szubko wdrożyć. Ale nie róbmy już offtopicu i trzymajmy się głównego tematu.

Główny temat jest taki, że Piotrek robi coś rewelacyjnego i chętnie się tym pobawię :slight_smile:
(ale serio, dokumentacja od pierwszej godziny, bo inaczej łatwo być odrzuconym od eksperymentów)

[quote=Tomash]Główny temat jest taki, że Piotrek robi coś rewelacyjnego i chętnie się tym pobawię :slight_smile:
(ale serio, dokumentacja od pierwszej godziny, bo inaczej łatwo być odrzuconym od eksperymentów)[/quote]
https://github.com/qertoip/guru_watch - lepiej?

Czy czegoś istotnego brakuje jeszcze w dokumentacji / jest niejasne?

Dzięki za dokumentację, kawał dobrej roboty. Ale jak zwykle będę się czepiał. To jest przykładowa aplikacji, więc wypadałoby chyba opisać również jak dopisać nowe funkcjonalnośći, po ja po przeglądaniu podkatalogów, dalej nie mogę się połapać który plik uruchamia następne itd. Dodatkowo co mi się nie podoba to aplikacja w aplikacji.

sorry ale czepiasz sie za bardzo kolegi

Tomash wysłuchałem prezentacji, przejrzałem aplikację Piotrka i muszę stwierdzić, że jednak to nie jest to samo co ja chcę zrealizować. W prezentacji i aplikacji poruszony jest problem zmiana logiki aplikacji która jest obecnie stosowana w coś co się wytwarza w trakcie projektowania aplikacji. Mi jednak chodzi że zmodyfikować tylko część łączącą się z bazą danych czyli modele. Tak żeby było one niezależne od bazy danych i aby można było w trakcie działania plikacji za pomocą jednej metody przenieść dane z jednej bazy danych do innej (np. pomiędzy ActiveRecord a MogoMapper/MongoId)

Nic prostszego:

[code=Ruby]# User is an entity. Entities are backend-agnostic. Entities do NOT derive from ActiveRecord::Base.
class User < Entity
attribute :id, type: Integer
attribute :name, type: String
end

Connect to the ActiveRecord backend

ar_backend = RubyPersistenceAPI::ActiveRecord::Backend.new
ar_backend.connect!( ar_config )

Connect to the MongoMapper backend

mm_backend = RubyPersistenceAPI::MongoMapper::Backend.new
mm_backend.connect!( mm_config )

Copy user from the ActiveRecord backend to the MongoMapper backend

user = ar_backend[User].find( 1 )
mm_backend[user].save![/code]
To co tutaj używam to proponowane Ruby Persistence API - bardzo podobne do AREL-a ale niefiksujące się na relacyjnych bazach danych. Zauważmy, że metody find() i save!() zachowują się tak jak jesteśmy przyzwyczajeni, tyle że nie są metodami encji. Są metodami backendu.

Adapter do ActiveRecorda w tym wąskim zakresie już nawet działa. Adapter do MongoMappera musiałbyś sobie napisać.

Masz na myśli, że to co przypomina railsy jest w katalogu app/frontends/web?

To nie jest aplikacja. To tylko frontend. Nie ma tam modeli, nie ma katalogu db itd. Tylko kontrolery webowe + widoki.

Czyli w tym momencie pomimo, że twója propozycja aplikacji działa i w teorii pozwala na połączenie się z różnymi bazami danych, to na tą chwilę łączy się z ActiveRecord. Mój gem multiz_mapper (nie nadpisuje już missing method, trochę go zmodyfikowałem) pozwala na połączenie z dowolnym mapperem.

Twój projekt może jest i ciekawy, ma za mało przykładów. W przed ostatniej twojej wiadomości dopiero zobaczyłem jak wykorzystać przełączanie się pomiędzy adapterami. Niestety większość dostępnych gemów chyba miałaby pewne problemy z wykorzystaniem w takiej aplikacji.