2012-12-30 11 views
11

Ich habe ein Buch und herunterladen Modell, das viele Eigenschaften teilen, so ist es mein Ziel, die gemeinsamen Attribute von einem DownloadableResource Modell zu erben.
hatte einen Blick auf STI, aber ich ging die abstract base model class Art und Weise statt:Implementieren abstrakte Basismodellklasse, die Rails Way ™

  • Modelle:

    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 
    
  • Migrationen:

    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 
    

Nach der Migration, wenn ich Erstellen Sie ein neues Buch, das Ergebnis ist weit von erwartet:

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

Kann jemand Schuppen bitte etwas Licht auf, wie die abstrakte Basis Model-Klasse Technik zu implementieren, so Active Modelle gemeinsamen Code über inheritance teilen können noch auf verschiedene Datenbanktabellen beibehalten werden?

+0

Ein Weg ist eine Zusammensetzung anstelle von Vererbung. Ein paar Beispiele: http://rails-bestpractices.com/posts/17-extract-into-module – VadimAlekseev

+0

Als eine Randnotiz, auch wenn Sie mit zwei ähnlich strukturierten Tabellen gehen, können Sie zumindest Ihre Migrationen DRY halten, indem Sie zuerst alle erstellen Tabellen mit nur ihren eindeutigen Feldern und dann so etwas wie '[: Bücher,: Downloads] .each do | table | change_table-Tabelle do | t | t.text: Beschreibung # ... Ende Ende' – Janosch

Antwort

9

Wenn Sie ein Modell als abstrakt deklarieren, sagen Sie tatsächlich, dass es keine zugrunde liegende Tabelle gibt und Sie Unterklassen zulassen möchten. Das heißt:

  • Sie brauchen nicht die downloadable_resources Tabelle
  • Book.table_name druckt books statt downloadable_resources

Wie @Finbarr bereits erwähnt, bedeutet dies auch, dass beide Book und Download Modelle benötigen um alle Attribute in ihren Tabellen zu haben.

Was ist das eigentlich nützlich für dann? Meiner Meinung nach nicht viel. Sie können Validierungen, Bereiche usw. teilen, aber Sie können all dies leichter erreichen, indem Sie benutzerdefinierte Module hinzufügen.

Um Ihr Problem zu lösen, würde ich wahrscheinlich mit einem anderen Ansatz gehen. Ich würde ein anderes Modell namens DownloadableContent erstellen, das in sich abgeschlossen wäre. Es würde Validierungen beinhalten und die Tabelle hätte alle Attribute. Und schließlich würden die Modelle Book und Download eine polymorphe has_one-Beziehung zu dem Modell DownloadableContent haben.

Sie könnten mit dem STI-Ansatz gehen, aber ich mag es im Allgemeinen nicht, alle benutzerdefinierten Attribute zusammen zu mischen.

5

In diesem Fall sollte keine downloadable_resources Tabelle vorhanden sein. Sowohl Ihre Bücher als auch Ihre Download-Tabellen sollten alle benötigten Felder angeben.

+2

Warum? Was macht diesen Fall für die Vererbung ungeeignet? Und wie entscheidet man, wann es sich lohnt zu erben und wann nicht? –

Verwandte Themen