如何在Rails中指定与自定义主键的多态关联

时间:2013-01-08 00:11:10

标签: ruby-on-rails polymorphic-associations

我有一些使用paper_trail进行版本跟踪的ActiveRecord类。 AR类具有基于其表名称的自定义主键(例如Item.ItemID而不是Item.id),以遵守业务数据库约定。

paper_trail指定每个跟踪类的多态关系,因此:

class TrackedExample < ActiveRecord::Base
    set_table_name 'TrackedExample'
    set_primary_key 'TrackedExampleID'

    # simplified from https://github.com/airblade/paper_trail/blob/master/lib/paper_trail/has_paper_trail.rb
    has_many :versions
        :class_name => 'Version'
        :as         => :item,
end

class AnotherTrackedExample
    set_table_name 'AnotherTrackedExample'
    set_primary_key 'AnotherTrackedExampleID'

    has_many :versions
        :class_name => 'Version'
        :as         => :item,
end

# from https://github.com/airblade/paper_trail/blob/master/lib/paper_trail/version.rb
class Version
    belongs_to :item, :polymorphic => true
    ...
 end

如果我没有使用自定义主键,则版本对象可以使用Version#item引用跟踪对象(即它是版本的对象)。当我尝试它时,我收到一个错误:

# This should give back `my_tracked_example`
my_tracked_example.version.first.item

=> TinyTds::Error: Invalid column name 'id'.: EXEC sp_executesql N'SELECT TOP (1) [TrackedExample].* FROM [TrackedExample] WHERE [TrackedExample].[id] = 1 ORDER BY TrackedExample.TrackedExampleID ASC'

有没有办法让Version#项执行正确的查询?我希望这样的事情:

EXEC sp_executesql N'SELECT TOP (1) [TrackedExample].* FROM [TrackedExample] WHERE [TrackedExample].[TrackedExampleID] = 1 ORDER BY TrackedExample.TrackedExampleID ASC'

我正在使用Rails 3.1.0,paper_trail 2.6.4和MS SQL Server通过TinyTDS和activerecord-sqlserver-adapter

编辑:我通过添加引用主键值的计算列TrackedExample.idAnotherTrackedExample.id来解决此问题。这不是一个合适的解决方案(Rails仍在进行错误的查询),但对其他人来说可能很有用。

MS SQL:

ALTER TABLE TrackedExample
    ADD COLUMN id AS TrackedExampleID

3 个答案:

答案 0 :(得分:1)

您不必在迁移文件中指定t.references :item,而是polymorphic: true。 您只需指定item_iditem_type,如下所示:

t.string :item_id

t.string :item_type

铁路将自动为primary_key选择正确的item_id和正确的类型。

答案 1 :(得分:0)

我没有尝试过,但这可能有用

class Version
  belongs_to :item, :polymorphic => true, :primary_key => 'TrackedExampleID'
  ...
end

答案 2 :(得分:0)

在搜索PaperTrail文档后,看起来你不能覆盖哪些列item_id引用(即Item表的主键),所以我认为你有两个主要选项:

<强> 1。创建一个没有该类名称的id列。因此,id代替TrackedExampleID

你说你已经做过这个快速修复。

<强> 2。分叉和修补PaperTrail,以便您在查询item_id时传递要使用的列。

这可以是set_primary_key 'TrackedExampleID'设置的值,也可以设置为has_paper_trail primary_key: 'TrakedExampleID'

让我们知道你最终会得到什么。