I have the following associations, basically I want to link via userid and not the id of the object.
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
There are two things going on here. I think you have switched the :has_one and :belongs_to declarations.
The :belongs_to
comes in the model that has the foreign-key.
The :has_one
comes in the model that is referred to (if it is only one, otherwise if many rows :belong_to the same, it is a has_many of course). For more info read here.
First, you will need to specify (overrule) the primary key of the model. Here i am assuming a user can have many tweets instead of just one (otherwise replace by :has_one
).
class UserProfile
set_primary_key :userid
has_many :tweets
end
then you need to adjust your :has_one
declaration:
class Tweet
belongs_to :user_profile, :foreign_key => :userid
end
Then, secondly, once your relations are setup correctly, there is no need to assign both :user_profile
or :userid
at creation time. Either you create a new UserProfile
and the foreign-keys will automatically by correct, or you assign an userid
of an existing profile.
Hope this helps.
cite@antiope:/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
class like that affected only the current controller or all actions). Still, it's only what I consider to be a workaround.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With