2009-09-10 20 views
7

Mam następujące powiązania, zasadniczo chcę połączyć za pośrednictwem identyfikatora użytkownika, a nie id obiektu.Szyny - Zastąp klucz podstawowy 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

to "personA" wchodzące w twoją bazę danych? – ErsatzRyan

+0

To mija, więc tak:

 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

Czy jest jakiś powód, dla którego musisz użyć identyfikatora użytkownika jako klucza obcego? Dlaczego nie wystarczy użyć klucza podstawowego powiązanego pola. – jonnii

Odpowiedz

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

dzięki, ale mój identyfikator jest identyfikatorem. Jednak do tego skojarzenia chcę użyć innej kolumny –

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 klasa podobna do tej dotyczyła tylko bieżącego kontrolera lub działań wszystkich). Jednak to tylko to, co uważam za obejście.

1

Są tu dwie rzeczy. Myślę, że zmieniłeś: has_one i: belongs_to deklaracje.

Model :belongs_to występuje w modelu z kluczem obcym. Model :has_one występuje w modelu, do którego się odnosi (jeśli jest tylko jeden, w przeciwnym razie, jeśli wiele wierszy: należą do tego samego, jest to oczywiście wiele). Aby uzyskać więcej informacji, przeczytaj here.

Najpierw należy określić (zastąpić) klucz podstawowy modelu. Zakładam, że użytkownik może mieć wiele tweetów zamiast jednego (w innym przypadku zastąpić je :has_one).

class UserProfile 
    set_primary_key :userid 
    has_many :tweets 
end 

następnie trzeba dostosować swoją deklarację :has_one:

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

Następnie, po drugie, gdy Twoje relacje są ustawione prawidłowo, nie ma potrzeby, aby przypisać zarówno :user_profile lub :userid w momencie tworzenia. Albo utworzysz nowy UserProfile, a klucze obce będą automatycznie poprawne, albo przypiszesz userid istniejącego profilu.

Mam nadzieję, że to pomoże.

Powiązane problemy