我有一些使用paper_trail进行版本跟踪的ActiveRecord类。 AR类具有基于其表名的自定义主键(例如Item.ItemID
而不是Item.id
),以便遵守业务DB约定。
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'
我通过TinyTDS和activerecord-sqlserver-adapter使用Rails 3.1.0,paper_trail 2.6.4和MS SQL Server。
编辑:我通过添加引用主键值的计算列TrackedExample.id
和AnotherTrackedExample.id
解决了这个问题。这不是一个合适的解决方案(Rails仍在进行错误的查询),但它可能对其他人很有用。
MS SQL:
ALTER TABLE TrackedExample
ADD COLUMN id AS TrackedExampleID
而不是在迁移文件中指定t.references :item
,polymorphic: true
。你只需要指定item_id
和item_type
如下:
t.string :item_id
t.string :item_type
Rails将自动为primary_key
选择正确的item_id
并更正类型。
我没试过,但这可能会奏效
class Version
belongs_to :item, :polymorphic => true, :primary_key => 'TrackedExampleID'
...
end
在搜索PaperTrail文档后,看起来你不能覆盖item_id
引用的列(即Item表的主键),所以我认为你有两个主要选项:
1.创建一个没有该类名称的id
列。所以,id
而不是TrackedExampleID
。
你说你已经做过这个快速修复。
2.分叉和修补PaperTrail,以便在查询item_id
时传递要使用的列。
这可以是用set_primary_key 'TrackedExampleID'
设置的值,也可以是像has_paper_trail primary_key: 'TrakedExampleID'
那样设置的值。
让我们知道你最终得到了什么。