【问题标题】:Referencing foreign keys with DataMapper使用 DataMapper 引用外键
【发布时间】:2011-03-31 16:46:44
【问题描述】:

我一直在看这个:

http://datamapper.org/docs/find

虽然我知道这很简单,但我无法看到我正在寻找的东西。

我有两张表格,分别是scans 和stations,以及相关字段:

STATIONS - id (primary key), name
SCANS    - id (primary key), item_id, in_station, out_station

其中in_stationout_stationstations 表中id 字段的外键。

我有一个Scan 对象

class Scan
    include DataMapper::Resource

    property :id,                       Integer, :key => true
    property :item_id,                  Integer
    property :in_station,               Integer
    property :out_station,              Integer
end

所以现在,我可以使用Scan.all(:item_id => @barcode) 来获取特定项目的所有扫描,并且我有in_station id 和out_station id。但是,获取 names 而不是 id 的最佳方式是什么。我认为这比每次扫描调用Station.get(:id=> scan.in_station) 都要容易。

这很容易使用 SQL,但是我如何更改 Scan/Station 以获取名称或拥有一个作为 Station 对象的属性,以便我可以执行 scan.station.name 之类的操作?

编辑:

我几乎已经完成了这项工作。我有一个 Station 课程:

class Station
    include DataMapper::Resource

    property :id, Integer, :key => true
    property :name, String
end

我在Scan 中删除了property :in_stationproperty :out_station 并替换为:

belongs_to :in_station,        :model => 'Station', :child_key => 'id'
belongs_to :out_station,       :model => 'Station', :child_key => 'id'

我认为/希望是说“有一个名为 in_station 的字段是 Station 表的外键,而一个名为 out_station 的字段是相同的”。事实上,in_station 和 out_station 现在是 Station 的实例,但是,它们是对象。即使 in_station 和 out_station 是不同的值,我在每次扫描时都会得到相同的对象。我做错了什么,我怎么能指出 in_station 和 out_station 都是对 Station 的引用,但是当它们的 id 不同时,我期望不同的对象。

【问题讨论】:

  • 查看在数据库中为扫描表创建的字段。就像我在下面所说的那样,尽管名称“child_key”暗示了其他情况,但您需要使用如下所示的名称。你的belongs_to 行说的是“扫描属于一个名为‘in_station’的站,并将加载一个与名为id 的扫描属性匹配的id 的站。”那不是你想要的。您希望“扫描属于具有名为 'in_station' 的关联的工作站,并将加载具有与名为 in_station_id 的扫描属性匹配的 id 的工作站。”

标签: ruby-on-rails ruby datamapper


【解决方案1】:

这样做怎么样:

class Station
  include DataMapper::Resource

  property :id, Serial
  # rest of the properties

  has n, :scans
end

class Scan
  include DataMapper::Resource

  property :id, Serial
  # rest of the properties

  belongs_to :station
end

然后您只需执行此操作即可访问关联的电台:

station = Station.create
scan    = station.scans.create

scan.station # returns the associated station

这应该适合您的架构。

【讨论】:

  • 我刚刚更新了问题,缺乏清晰性。 in_station 和 out_station 和 ids 并引用站表/模型中的 id。我希望能够通过Scan.all(:item_id => @barcode) 对特定项目进行所有扫描,然后通过这些扫描并获取它们被扫描进出的名称。现在我可以得到它被扫描进出的 id,我只想要名字,而 id 是有名字的车站表的外键。如何告诉 DataMapper in_station 和 out_station 是站?
【解决方案2】:

假设我们不想更改底层 SQL 架构。所以我们必须告诉 DataMapper 使用现有的外键名称(in_station 和 out_station)。扭曲的是,如果关联名称与子键相同,DataMapper 将阻塞。这就是为什么我在关联名称上有“my_”前缀的原因。

class Scan
  include DataMapper::Resource

  #rest of the properties

  belongs_to :my_in_station, :model => 'Station', :child_key => 'in_station'
  belongs_to :my_out_station, :model => 'Station', :child_key => 'out_station'
end

用法

s = Scan.get(id)
s.my_in_station.name
s.my_out_station.name

【讨论】:

  • 好吧,原谅我的无知,但是一旦我这样做了(我将 :child_keys 更改为只是 'id',因为那是 Station 中的字段名称,或者应该颠倒它),如何访问该名称?我有一堆 Scan 对象,我想要扫描它们的电台名称和扫描出它们的名称。
  • 不要更改 :child_key。 DataMapper 已经知道“Station”模型的键是“id”。我将添加一个使用示例。
  • 如果我将 :child_key 更改为任何内容 id 我会收到错误 - 堆栈级别太深或字段列表中的未知列 'in_station_id'。
  • :child_key 视为外键。因此,您使用它来表示“将具有此名称的外键添加到当前模型。”
  • 那些迁移是什么?给定的模型与 mysql 后端匹配。表中的任何地方都没有名为“in_station_id”的键,扫描表中只有 in_station 和 out_station,它们都引用了 station 表中简称为“id”的字段。如果我将 child_key 作为 'in_station' 和 'out_station' 我得到一个错误:堆栈级别太深 * 文件:many_to_one.rb * 位置:target_key * 行:271 如果我将它们都放入 id,我会得到一个 Station 对象,但对于 in 和 out_station 都是相同的,即使在 DB 中指示了不同的站 ID。
猜你喜欢
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 2023-03-10
  • 1970-01-01
  • 2013-01-25
相关资源
最近更新 更多