2009-09-10 56 views
7

我有以下關聯,基本上我想通過用戶標識而不是對象的id鏈接。Rails - 覆蓋has_one上的主鍵

class Tweet < ActiveRecord::Base 
    has_one :user_profile, :primary_key => 'userid', :foreign_key => 'twitter_userid'

 
class UserProfile < ActiveRecord::Base 
    belongs_to :tweet, :foreign_key => 'userid'

However the following spec fails as twitter_userid is reset to the id of the object

 
it "should have the user's twitter id set on their user profile" do 
    t = Tweet.new(:twitter_id => 1, 
        :status => 'Tester', 
        :userid => 'personA', 
        :user_profile => UserProfile.new(:twitter_userid => 'personA', :avatar => 'abc')) 
    t.save! 
    t.user_profile.twitter_userid.should == 'personA' 
end 

should have the user's twitter id set on their user profile

expected: "personA", 
    got: 216 (using ==)

However, the following does pass:

 
it "should return the correct avatar after being saved" do 
    t = Tweet.new(:twitter_id => 1, 
        :status => 'Tester', 
        :userid => 'personA', 
        :user_profile => UserProfile.new(:twitter_userid => 'personA', :avatar => 'abc')) 
    t.save! 

    t.user_profile.avatar.should == 'abc' 
end 

How can I force it to use userid and not id?

Thanks

Ben

+0

是'personA'進入你的分貝? – ErsatzRyan 2009-09-10 19:31:24

+0

這是通過,所以是的,它是:

 it "should save" do t = Tweet.new(:twitter_id => 1, :status => 'Tester', :userid => 'personA', :user_profile => UserProfile.new(:twitter_userid => 'personA', :avatar => 'abc')) t.save! t.userid.should == 'personA' t.new_record?.should == false t.valid?.should == true t.user_profile.new_record?.should == false t.user_profile.valid?.should == true end 
2009-09-10 20:23:33

+0

是否有你需要使用userid作爲外鍵的原因?爲什麼不使用關聯字段的主鍵。 – jonnii 2009-09-10 21:08:26

回答

0

If the primary key on your db is not called id then you want to do something like this:

class Tweet < AR:B 
    set_primary_key "userid" 
end 

However, I'm not sure I totally understand the question. Is there a reason you want to step outside of the rails conventions?

+0

謝謝,但我的身份證是身份證。然而,對於這種關聯,我想使用不同的列 – 2009-09-10 19:21:59

1
[email protected]:/tmp/foo$ script/console 
Loading development environment (Rails 2.3.4) 
>> t = Tweet.new(:twitter_id => 1, 
?>     :status => 'Tester', 
?>     :userid => 'personA', 
?>     :user_profile => UserProfile.new(:twitter_userid => 'personA', :avatar => 'abc')) 
=> #<Tweet id: nil, twitter_id: 1, status: "Tester", userid: "personA", created_at: nil, updated_at: nil> 
>> Tweet.set_primary_key :userid 
=> nil 
>> t.save 
    Tweet Create (0.4ms) INSERT INTO "tweets" ("created_at", "updated_at", "userid", "twitter_id", "status") VALUES('2009-09-10 20:19:36', '2009-09-10 20:19:36', 'personA', 1, 'Tester') 
    UserProfile Create (0.1ms) INSERT INTO "user_profiles" ("twitter_userid", "created_at", "updated_at", "avatar") VALUES('personA', '2009-09-10 20:19:36', '2009-09-10 20:19:36', 'abc') 
=> true 
>> Tweet.set_primary_key :id 
=> nil 

Modfiying the model a split second before saving it might be an acceptable solution if you only have to redefine the primary key in one place (I didn't test if modifying the Tweet類一樣,隻影響當前控制器或所有動作)。不過,這只是我認爲是一種解決方法。

1

有兩件事情在這裏。我認爲你已經切換了:has_one和:belongs_to聲明。

:belongs_to進入具有外鍵的模型中。 :has_one出現在被引用的模型中(如果它只有一個,否則如果許多行:belongs_to相同,則當然是has_many)。欲瞭解更多信息,請閱讀here

首先,您需要指定(推翻)模型的主鍵。在這裏,我假設用戶可以有許多推文而不是一個(否則替換爲:has_one)。

class UserProfile 
    set_primary_key :userid 
    has_many :tweets 
end 

那麼你就需要調整您的:has_one聲明:

class Tweet 
    belongs_to :user_profile, :foreign_key => :userid 
end 

然後,其次,一旦你的關係是正確的設置,也沒有必要在創建時同時將與:user_profile:userid。您可以創建一個新的UserProfile,並且外鍵將自動更正,或者分配現有配置文件的userid

希望這會有所幫助。