2009-09-10 14 views
7

Ich habe die folgenden Assoziationen, grundsätzlich möchte ich über Benutzer-ID verknüpfen und nicht die ID des Objekts.Rails - Override Primärschlüssel auf 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

geht 'personA' in Ihre db? – ErsatzRyan

+0

Das geht, also ja ist es:

 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 

+0

Gibt es einen Grund, warum Sie Benutzer-ID als Fremdschlüssel verwenden müssen? Warum nicht einfach den Primärschlüssel des zugehörigen Feldes verwenden? – jonnii

Antwort

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

danke, aber meine ID ist ID. Für diese Assoziation möchte ich jedoch eine andere Spalte verwenden –

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 Klasse wie das betrifft nur den Stromregler oder alle Aktionen). Dennoch ist es nur das, was ich als Problemumgehung betrachte.

1

Hier gehen zwei Dinge vor sich. Ich denke du hast die: has_one und: gehört_to Deklarationen umgestellt.

Die :belongs_to kommt in dem Modell, das den Fremdschlüssel hat. Das :has_one kommt in dem Modell, auf das verwiesen wird (wenn es nur eins ist, andernfalls, wenn viele Zeilen: gehören zu demselben, es ist natürlich ein has_many). Für weitere Informationen lesen Sie here.

Zuerst müssen Sie den Primärschlüssel des Modells angeben (überschreiben). Hier gehe ich davon aus, dass ein Benutzer viele Tweets anstelle von nur einem haben kann (ansonsten durch :has_one ersetzen).

class UserProfile 
    set_primary_key :userid 
    has_many :tweets 
end 

dann müssen Sie Ihre :has_one Erklärung anzupassen:

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

Dann zweitens, wenn Ihre Beziehungen sind richtig eingestellt, gibt es keine Notwendigkeit, sowohl :user_profile oder :userid zum Zeitpunkt der Erstellung zuzuweisen. Entweder Sie erstellen eine neue UserProfile und die Fremdschlüssel werden automatisch korrekt, oder Sie weisen eine userid eines vorhandenen Profils zu.

Hoffe, das hilft.