如何:DataMapper中的单表继承?

时间:2012-12-13 16:27:55

标签: sinatra single-table-inheritance sti ruby-datamapper sqlite3-ruby

我正在学习 Sinatra (1.3.2)并选择使用 DataMapper (1.2.0)作为ORM和内存 SQLite (1.3.6)DB开始。
两个模型BooksDownloads共享大多数属性,因此我研究了在DataMapper中声明STI(单表继承)的模型。阅读the docs,感谢Types::Discriminator,这似乎是小菜一碟。

我将所有常见问题抽象为DownloadableResource

class DownloadableResource
  include DataMapper::Resource

  property :id,           Serial
  property :created_at,   DateTime
  property :modified_at,  DateTime
  property :active,       Boolean,  default: true

  property :position,     Integer

  property :title,        String,   required: true
  property :url,          URI,      required: true
  property :description,  Text,     required: true

  property :type,         Discriminator
end

关注the example,我认为这就像指定需要扩展的内容一样简单:

class Book < DownloadableResource
  property :cover_url,    URI
  property :authors,      String,   required: true, length: 255
end

class Download < DownloadableResource
  property :icon_url,     URI
end

但这给了我以下错误:

  

DataObjects :: SyntaxError:重复列名:id (代码:1,sql state :, query:ALTER TABLE“ downloadable_resources ”ADD COLUMN“id”INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,uri:sqlite3 :: memory:?scheme = sqlite&amp; user =&amp; password =&amp; host =&amp; port =&amp; query =&amp; fragment =&amp; adapter = sqlite3&amp; path =:memory: )

删除id时产生另一个(明显的)错误:

  

DataMapper :: IncompleteModelError:DownloadableResource必须有一个有效的密钥

我通过向include DataMapper::ResourceBook添加Download来解决这个问题,然后Book需要一个有效的密钥,现在看起来像这样:

class Book < DownloadableResource
  include DataMapper::Resource

  property :id,           Serial

  property :cover_url,    URI
  property :authors,      String,   required: true, length: 255
end

同样适用于Download,但现在的问题是:

  

DataObjects :: SyntaxError:重复列名:id (代码:1,sql state :, query:ALTER TABLE“ books ”ADD COLUMN“id”INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,uri:sqlite3 :: memory:?scheme = sqlite&amp; user =&amp; password =&amp; host =&amp; port =&amp; query =&amp; fragment =&amp; adapter = sqlite3&amp; path =:memory: )

开始觉得我要进入圈子,在DataMapper中实现单表继承的正确方法是什么?


PS:我看过了

但我仍有这个问题。

1 个答案:

答案 0 :(得分:1)

我会推荐这种方法:

module DownloadableResource

  def self.included base
    base.class_eval do
      include DataMapper::Resource

      property :created_at,   DateTime
      property :modified_at,  DateTime
      property :active,       base::Boolean,  default: true

      property :position,     Integer

      property :title,        String,   required: true
      property :url,          base::URI,      required: true
      property :description,  base::Text,     required: true

      property :type,         base::Discriminator
    end
  end
end

class Book
  include DownloadableResource
  property :id, Serial
  # other properties
end

class Download
  include DownloadableResource
  property :id, Serial
  # other properties
end