Reputation: 2324
I have a few ActiveRecord classes using paper_trail for version tracking. The AR classes have custom primary keys based on their table names (e.g. Item.ItemID
instead of Item.id
) in order to adhere to business DB conventions.
paper_trail specifies a polymorphic relationship on each of the tracked classes, thus:
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
If I were not using custom primary keys, the version object could refer to the tracked object (i.e. the object of which it is a version) using Version#item
. When I try it, I get an error:
# 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'
Is there a way to get Version#item to perform the correct query? I would expect something like this:
EXEC sp_executesql N'SELECT TOP (1) [TrackedExample].* FROM [TrackedExample] WHERE [TrackedExample].[TrackedExampleID] = 1 ORDER BY TrackedExample.TrackedExampleID ASC'
I'm using Rails 3.1.0, paper_trail 2.6.4 and MS SQL Server through TinyTDS and activerecord-sqlserver-adapter.
EDIT: I've worked around the problem by adding computed columns TrackedExample.id
and AnotherTrackedExample.id
that refer to the primary key values. This isn't a proper solution (Rails is still making the wrong query), but it may be useful to others in a hurry.
MS SQL:
ALTER TABLE TrackedExample
ADD COLUMN id AS TrackedExampleID
Upvotes: 4
Views: 3754
Reputation: 101
Rather than specifying t.references :item
, polymorphic: true
in your migration file.
You simply have to specify the item_id
and item_type
as follows:
t.string :item_id
t.string :item_type
Rails will automatically select the correct primary_key
for the item_id
and correct type.
Upvotes: 2
Reputation: 47471
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.
Upvotes: 0
Reputation: 4296
I haven't tried it, but this might work
class Version
belongs_to :item, :polymorphic => true, :primary_key => 'TrackedExampleID'
...
end
Upvotes: 1