3

我有一些使用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#item 执行正确的查询?我会期待这样的事情:

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.idAnotherTrackedExample.id引用主键值来解决这个问题。这不是一个合适的解决方案(Rails 仍在进行错误的查询),但它可能对其他匆忙的人有用。

微软 SQL:

ALTER TABLE TrackedExample
    ADD COLUMN id AS TrackedExampleID
4

3 回答 3

2

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

t.string :item_id

t.string :item_type

Rails 会自动primary_keyitem_id正确的类型选择正确的。

于 2019-04-03T01:20:36.333 回答
0

我没试过,但这可能有效

class Version
  belongs_to :item, :polymorphic => true, :primary_key => 'TrackedExampleID'
  ...
end
于 2013-01-08T00:35:06.797 回答
0

After scouring the PaperTrail documents it doesn't look like you can override what column item_id references (i.e. the primary key of the Item's table), so I think you have two main options:

1. Create an id column that does not have the name of the class in it. So, id instead of TrackedExampleID.

You said you already did this as a quick fix.

2. Fork and patch PaperTrail to allow you to pass what column to use when querying for item_id.

This could either be the value set with set_primary_key 'TrackedExampleID' or it could be something set like has_paper_trail primary_key: 'TrakedExampleID'.

Let us know what you end up with.

于 2018-01-06T14:35:04.960 回答