Dziedziczenie pojedynczych tabel i gdzie go używać w Rails

Utknąłem w dziwnym problemie projektowym,

Pracuję nad dwoma rodzajami modeli profili,

  • profil użytkownika (należy do użytkownika)
  • Inne, które są utrzymywane w witrynie jako "boty" (nie należą do nikogo)

Typowe zachowanie oo tych dwóch typów profili jest takie samo, ale tylko ważne atrybuty/właściwości są wspólne ( bardzo ważne w liczbie 5-6), inne właściwości, takie jak "zainteresowania itp"(Prawie 10-15 właściwości) nie są tam dla bot profile

Programista, który pracował nad tym wcześniej stworzył oddzielne modele / Kontrolery dla profili botów / profili użytkowników, co wszędzie tworzy dużo nadmiarowości, a także zgodnie z oczekiwaniami trudne do utrzymania, pisania testów itp.Chciałem to wyschnąć, przynajmniej rozwiązać niektóre / wszystkie problemy związane z redundancją.

Ktoś zasugerował dziedziczenie pojedynczej tabeli jako rozwiązanie

Ktoś zasugerował zamiast tego użycie skojarzeń polimorficznych.

Jakie jest lepsze podejście. Kiedy naprawdę używamy STI?

My own thought was STI jest używany najlepiej, gdy atrybuty są takie same dla Modeli i różnią się zachowaniem.

Myśli o tym, co mogę zrobić?

Author: Brian Tompsett - 汤莱恩, 2009-02-17

4 answers

Scharakteryzowanie STI jako najbardziej przydatne, gdy atrybuty są takie same, ale zachowanie różni się, jest "o prawo", ale być może trochę ograniczające. Lubię używać STI, gdy istnieje, jak sama nazwa wskazuje, wyraźna relacja dziedziczenia w stylu OO, a nie relacja w stylu bazy danych między obiektami różnych typów.

Jeśli istnieje wspólny kod między botami i użytkownikami, powiedziałbym, że STI brzmi jak zwycięzca. Jeśli jest tylko kilka wspólnych atrybutów, to prawdopodobnie mniej odpowiednie, ale nadal warto spróbować.

Jestem dość eksperymentalną osobą, więc polecam spróbować. Rozgałęź swój kod i przekształć modele w związek STI. Zobacz, czy to naprawdę wysusza rzeczy, lub po prostu zamienia jeden zestaw bólów głowy na jakiś inny problem.

Jedną z rzeczy, z której nie zobaczysz wielu korzyści, jest suszenie kontrolerów. Z mojego doświadczenia wynika, że modele STI nie często przekładają się na podobne Kontrolery. Ale to byłoby coś innego do eksperymentuj z. Czasami jest wygrana, czasami nie.

 35
Author: womble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-17 06:26:59

Napisałem artykuł na ten temat, zawierający kilka wskazówek dotyczących pracy z STI:

Dziedziczenie pojedynczej tabeli w Rails

W skrócie: pomiędzy obiektami musi istnieć wyraźna relacja dziedziczenia w stylu OO (jak wymownie twierdzi womble), a nie tylko niektóre wspólne dane. Jeśli nie ma naturalnej i oczywistej hierarchii klas, projekt STI może stać się trudny do utrzymania w miarę rozwoju aplikacji.

Po drugie, należy rozważyć, czy ważne jest, aby wszystkie dane w jednej tabeli. Dzięki polimorficznym asocjacjom zapytania do bazy danych staną się bardziej złożone i prawdopodobnie wolniejsze. Jeśli planujesz wymienić wszystkie obiekty razem na stronie (np. w tabeli) to STI może być drogą.

Po trzecie, upewnij się, że Twoje klasy dziecięce nie mają zbyt wielu unikalnych atrybutów. Przy wszystkich danych w jednej tabeli nie potrzebujesz zbyt wielu kolumn innych niż globalne. Nie tylko zajmują one miejsce (nie jest to poważny problem), ale tworzą strukturę danych mylące. Jeśli masz" specjalne " kolumny, powinieneś je wyraźnie wyjaśnić w swoim kodzie.

Wreszcie, jeśli używasz STI, zdecydowanie zalecam użycie jednego kontrolera dla wszystkich modeli dzieci. Główną funkcją kontrolera jest zapewnienie dostępu do obiektów, a jeśli obiekty muszą być dostępne na bardzo różne sposoby, STI może nie być właściwym wyborem projektowym.

Zajrzyj do mojego artykułu (link powyżej), aby uzyskać więcej przydatnych wskazówek.

 29
Author: Alex Reisner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-24 22:22:19

Prawdopodobnie użyłbym albo STI, albo żadnych specjalnych funkcji. Możesz być w stanie nazwać wszystko profilem i wiesz, czy to był "bot", jeśli jego użytkownik był zerowy. Można również zapisać pole "type" bez użycia STI.

Pewne rzeczy wpłynęłyby na moją decyzję o użyciu STI:

  • czy istnieje logika specyficzna dla bota
  • ile jest botów w porównaniu z profilami użytkowników (mała liczba botów oznacza, że STI jest OK-dużo botów i może gdzieś je schowam else)

Powodem unikania STI jest to, że czasami może stać ci na drodze. Na przykład zmiana obiektu z jednego typu na inny może być dość irytująca (w tym przypadku bota na profil). Czasami lepsze jest proste pole "Typ".

Warto zauważyć, że prawdopodobnie będziesz potrzebował wspólnej klasy bazowej, jeśli używasz STI. Więc możesz chcieć Profile, BotProfile, i UserProfile. Nazwiska zależą od Ciebie. :)

 5
Author: wuputah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-17 06:37:14

Jeden z rails STI-większość wtyczek (i tak dalej) nie obsługuje go w pełni. Znajdziesz się łatanie wielu popularnych.

 4
Author: Sarah Mei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-18 00:23:20