I know I can use :finder_sql to manually define the SQL to use to fetch associated records, but I'm wondering if ActiveRecord uses the :primary_key and :foreign_key options on an association to generate the joining SQL. It doesn't appear to, but am I just missing something here?
我知道我可以使用:finder_sql手動定義SQL以獲取關聯的記錄,但我想知道ActiveRecord是否在關聯上使用:primary_key和:foreign_key選項來生成加入的SQL。看起來沒有,但我是不是漏掉了什么?
Update: To be more explicit, my question is: Is there some way to keep the id columns as the primary key but have AR use a different column for the joins when I specify my relationships?
更新:要更加明確,我的問題是:是否有一些方法可以將id列保持為主鍵,但是當我指定我的關系時,AR會使用不同的列作為連接嗎?
Here's example model definitions and an example console session...
下面是示例模型定義和示例控制台會話……
Models
模型
class Post < ActiveRecord::Base
#Columns are: id:integer uuid:string name:string
has_many :assignments, :foreign_key => 'post_uuid', :primary_key => 'uuid'
has_many :categories, :through => :assignments
end
class Category < ActiveRecord::Base
#Columns are id:integer uuid:string name:string
has_many :assignments, :foreign_key => 'category_uuid', :primary_key => 'uuid'
end
class Assignment < ActiveRecord::Base
#Columns are post_uuid:string category_uuid:string
belongs_to :post, :foreign_key => 'uuid', :primary_key => 'post_uuid'
belongs_to :category, :foreign_key => 'uuid', :primary_key => 'category_uuid'
end
Console Session
控制台會話
#Make a Post
>> p = Post.create(:uuid => '123', :name => 'The Post')
Post Create (0.9ms) INSERT INTO "posts" ("name", "created_at", "uuid", "updated_at") VALUES('The Post', '2010-02-04 00:05:13', '123', '2010-02-04 00:05:13')
=> #<Post id: 2, uuid: "123", name: "The Post", created_at: "2010-02-04 00:05:13", updated_at: "2010-02-04 00:05:13">
#Make a Category
>> c = Category.create(:uuid => '456', :name => 'The Category')
Category Create (0.5ms) INSERT INTO "categories" ("name", "created_at", "uuid", "updated_at") VALUES('The Category', '2010-02-04 00:05:30', '456', '2010-02-04 00:05:30')
=> #<Category id: 2, name: "The Category", uuid: "456", created_at: "2010-02-04 00:05:30", updated_at: "2010-02-04 00:05:30">
#Make an Assignment, associating the post and the category
>> a = Assignment.create(:post_uuid => p.uuid, :category_uuid => c.uuid)
Assignment Create (0.4ms) INSERT INTO "assignments" ("created_at", "updated_at", "post_uuid", "category_uuid") VALUES('2010-02-04 00:05:50', '2010-02-04 00:05:50', '123', '456')
=> #<Assignment id: 2, post_uuid: "123", category_uuid: "456", created_at: "2010-02-04 00:05:50", updated_at: "2010-02-04 00:05:50">
#Try to fetch the category from the post object, which generates the wrong SQL
>> p.categories
Category Load (0.0ms) SQLite3::SQLException: no such column: assignments.uuid: SELECT "categories".* FROM "categories" INNER JOIN "assignments" ON "categories".id = "assignments".uuid WHERE (("assignments".post_uuid = 2))
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: assignments.uuid: SELECT "categories".* FROM "categories" INNER JOIN "assignments" ON "categories".id = "assignments".uuid WHERE (("assignments".post_uuid = 2))
[...Stack trace edited out...]
#Also odd: Try to fetch the post from the Association, no SQL generated, we just get nil
>> a.post
=> nil
4
I was able to get your code to work by changing your model definitions.
通過更改模型定義,我可以讓您的代碼工作。
class Post < ActiveRecord::Base
set_primary_key :uuid # tell the model about the non standard primary key
has_many :assignments, :foreign_key => 'post_uuid'
has_many :categories, :through => :assignments
end
class Category < ActiveRecord::Base
set_primary_key :uuid # tell the model about the non standard primary key
has_many :assignments, :foreign_key => 'category_uuid'
end
class Assignment < ActiveRecord::Base
belongs_to :post, :foreign_key => 'post_uuid' # notice the value for the foreign_key
belongs_to :category, :foreign_key => 'category_uuid' # notice the value for the foreign_key
end
Apart from this, change the migration file to nominate the non standard primary key(uuid) in Category and Post models.
除此之外,更改遷移文件以在類別和Post模型中指定非標准主鍵(uuid)。
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts, {:id => false} do |t|
t.string :uuid, :primary => true, :limit => 20
t.string :name
t.timestamps
end
end
def self.down
drop_table :posts
end
end
class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories, {:id => false} do |t|
t.string :uuid, :primary => true, :limit => 20
t.string :name
t.timestamps
end
end
def self.down
drop_table :categories
end
end
You can't set the value for uuid via mass assignments while calling new/create method. You have to set the value for the primary_key explicitly.
在調用new/create方法時,不能通過大量分配來設置uuid的值。必須顯式地為primary_key設置值。
# this will not work. uuid will be set to 0
p = Post.create(:uuid => '123', :name => 'The Post')
# this will work
p = Post.new(:name => 'The Post')
p.uuid = '123'
p.save
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2010/02/04/724f05ab07b4e3b9d09e12bf948cec0e.html。