2012-12-30 7 views
11

Mam Book i Pobierz model, który łączy wiele wspólnych cech, więc moim celem jest dziedziczą wspólne atrybuty z DownloadableResource modelu.
Gdyby spojrzeć na STI, ale poszedłem drogę abstract base model class Zamiast:wykonawcze Streszczenie Podstawowy model klasy, Rails Way ™

  • modele:

    class DownloadableResource < ActiveRecord::Base 
        self.abstract_class = true 
    
        attr_accessible :title, :url, :description, :active, :position 
        validates :title, :url, :description, presence: true 
        scope :active, where(active: true).order(:position) 
    end 
    
    class Book < DownloadableResource 
        attr_accessible :cover_url, :authors 
        validates :cover_url, :authors, presence: true 
    end 
    
    class Download < DownloadableResource 
        attr_accessible :icon_url 
        validates :icon_url, presence: true 
    end 
    
  • migracje:

    class CreateDownloadableResources < ActiveRecord::Migration 
        def change 
        create_table :downloadable_resources do |t| 
         t.string :title 
         t.string :url 
         t.text  :description 
         t.boolean :active,  default: false 
         t.integer :position 
         t.timestamps 
        end 
        end 
    end 
    
    class CreateBooks < ActiveRecord::Migration 
        def change 
        create_table :books do |t| 
         t.string :cover_url 
         t.string :authors 
         t.timestamps 
        end 
        end 
    end 
    
    class CreateDownloads < ActiveRecord::Migration 
        def change 
        create_table :downloads do |t| 
         t.string :icon_url 
         t.timestamps 
        end 
        end 
    end 
    

Po migracji, kiedy utwórz nową książkę, której wynik jest daleki od Oczekuje:

> Book.new 
=> #<Book id: nil, cover_url: nil, authors: nil, created_at: nil, updated_at: nil> 

Może ktoś proszę rzucić nieco światła na to, jak wdrożyć technikę Streszczenie Podstawowy model Class więc modele ActiveRecord mogą dzielić wspólny kod poprzez inheritance być jeszcze utrzymywały się do różnych tabel w bazie danych?

+0

Jednym ze sposobów jest kompozycja zamiast dziedziczenia. Przykład: http://rails-bestpractices.com/posts/17-extract-into-module – VadimAlekseev

+0

Na marginesie, nawet jeśli używasz dwóch podobnie skonstruowanych tabel, możesz przynajmniej utrzymać swoje migracje DRY, najpierw tworząc wszystkie tabele zawierające tylko swoje unikalne pola, a następnie robiące coś w rodzaju: '[: books,: downloads] .each do | table | change_table table do | t | t.text: description # ... koniec koniec' – Janosch

Odpowiedz

9

Deklarując model jako streszczenie, faktycznie mówisz, że nie ma żadnej tabeli bazowej i chcesz zezwolić na podklasę. Oznacza to, że:

  • Nie trzeba tabelę downloadable_resources
  • drukuje Book.table_name books zamiast downloadable_resources

Jak @Finbarr już wspomniano, oznacza to również, że oba Book i Download modele potrzebują mieć wszystkie atrybuty w swoich tabelach.

Co to właściwie jest przydatne? Moim zdaniem nie za dużo. Możesz udostępniać sprawdzanie poprawności, zakresy itp., Ale możesz to wszystko łatwiej osiągnąć, włączając niestandardowe moduły.

Aby rozwiązać Twój problem, prawdopodobnie podjąłbym inne podejście. Stworzyłbym inny model o nazwie DownloadableContent, który byłby samowystarczalny. Obejmie to sprawdzanie poprawności, a tabela będzie miała wszystkie atrybuty. I wreszcie modele Book i Download miałyby polimorficzny stosunek do modelu .

Możesz przejść z podejściem STI, ale generalnie nie lubię mieszać wszystkich niestandardowych atrybutów razem.

5

W tym przypadku nie powinno być tabeli downloadable_resources. Zarówno tabele książek, jak i pobrane powinny zadeklarować wszystkie potrzebne pola.

+2

Dlaczego? Co sprawia, że ​​ten przypadek nie nadaje się do dziedziczenia? A jak zdecydować, kiedy warto to odziedziczyć, a kiedy nie? –

Powiązane problemy