Szyny - użyj kolumny typu bez STI?

82

Chcę użyć kolumny o nazwie typebez wywoływania dziedziczenia pojedynczej tabeli (STI) - chcę po prostu typebyć zwykłą kolumną zawierającą String.

Jak mogę to zrobić bez oczekiwania przez Railsy, ​​że będę miał dziedziczenie pojedynczej tabeli i wyrzucania wyjątku The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.?

Jakieś pomysły, jak to zrobić?

Kwas
źródło

Odpowiedzi:

135

W Railsach 3.1 set_inheritance_columnjest przestarzałe, możesz również użyć niljako nazwy, na przykład:

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end
Valentin Nemcev
źródło
Właściwie wydaje się, że to się zmieniło rails 3.2. Według apidocka : „Ta metoda jest przestarzała lub przeniesiona do najnowszej stabilnej wersji. Tutaj pokazana jest ostatnia istniejąca wersja (v3.1.0). ' Dzięki za wskazówkę!
Batkins
Został wycofany w wersji 3.1 i usunięty w wersji 3.2, jak sądzę
Valentin Nemcev
2
@Batkins inheritance_columnCzytnik został przeniesiony (stąd powiadomienie „przestarzałe lub przeniesione”). Użycie bezpośredniego ustawienia inheritance_columnzmiennej instancji jest zamierzone i nie jest przestarzałe.
lulalala
Pracował w szynach 5.1
John Bachir
22

Możesz zastąpić nazwę kolumny STI za pomocą set_inheritance_column:

class Pancakes < ActiveRecord::Base
    set_inheritance_column 'something_you_will_not_use'
    #...
end

Więc wybierz nazwę kolumny, której nie będziesz używać do niczego i podaj ją set_inheritance_column.

mu jest za krótkie
źródło
2
czy muszę faktycznie utworzyć wspomnianą kolumnę w mojej bazie danych?
Kwas
Dziękuję, zadziałało. Ramy nie powinny NIGDY !!!!! ZAWSZE!!!! decydować, jakiego pola tabeli nie można nazwać. To zła kolacja dla starszych zestawów danych.
Jon
5
@Jon: Railsom nie zależy na starszych danych ani na dobrej współpracy z innymi, Rails ma do tego zbyt duże nastawienie. Możesz sprawić, że będzie się zachowywał z pewnym wysiłkiem, ale zawsze kończysz trochę walką, jeśli musisz zrobić coś, czego Railsy nie zaplanowały (co niestety obejmuje wiele podstawowych koncepcji dotyczących baz danych). OTOH, jestem zawodowym heretykiem, więc inni ludzie z Railsów z pewnością będą na mnie źli za wskazywanie na problemy ideologiczne :)
mi jest za krótkie
10
Myślę, że idea jest taka, że ​​Railsy / Ruby wolą konwencję od konfiguracji, więc starają się ją zoptymalizować pod kątem przypadków użycia, które uważają za poprawne.
Ibrahim
21

Wiem, że to pytanie jest dość stare i nieco odbiega od pytania, które zadajesz, ale zawsze robię, gdy mam ochotę nazwać typ kolumny lub coś_typ, szukam synonimu typu i używam go zamiast tego:

Oto kilka możliwości: rodzaj, sortowanie, różnorodność, kategoria, zestaw, gatunek, gatunek, porządek itp.

rii
źródło
10

Szyny 4.x

I napotkał problem w Rails 4aplikacji, ale w Rails 4set_inheritance_column metoda nie istnieje w ogóle, więc nie można z niego korzystać.

Rozwiązanie że pracował dla mnie było wyłączyć pojedynczej tabeli dziedziczenie nadrzędnymi ActiveRecord„s inheritance_columnmetody, na przykład:

class MyModel < ActiveRecord::Base

  private

  def self.inheritance_column
    nil
  end

end

Mam nadzieję, że to pomoże!

Itay Grudev
źródło
8
Prostsza wersja: class MyModel < ActiveRecord::Base self.inheritance_column = nil end. Źródła
Benj
1
U mnie działa w szynach 4.2.2. Być może nie zrestartowałeś serwera lub sprężyny po wprowadzeniu zmiany?
Benj
1
A prostsza wersja, którą skomentowałem, może przydać się innym użytkownikom. Jeśli chodzi o kwestię ponownego ładowania, nie jestem ekspertem, ale byłoby sensowne, gdyby właściwość klasy nie była automatycznie przeładowywana bez wyładowania i ponownego załadowania definicji klasy.
Benj,
2
Nie rozumiem Twojej reakcji, po prostu próbuję dodać przydatne uzupełnienie Twojej odpowiedzi. Dlaczego czujesz się urażony? Przychodzę w pokoju
Benj
2
@Benj Wygląda na to, że usunęli wszystkie komentarze, do których się odnosisz, więc teraz wygląda na to, że kłócisz się ze sobą. ;)
Joshua Pinter
0

Jeśli chcesz to zrobić dla wszystkich modeli, możesz umieścić to w inicjatorze.

ActiveSupport.on_load(:active_record) do
  class ::ActiveRecord::Base
    # disable STI to allow columns named "type"
    self.inheritance_column = :_type_disabled
  end
end
Bill Lipa
źródło
Albo jeszcze lepiej - w ApplicationRecord .
Alexander