2009-09-10 11 views
7

Tengo las siguientes asociaciones, básicamente quiero vincular a través del ID de usuario y no el ID del objeto.Rieles - Anular la clave primaria en 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

es 'personA' entrando en su db? – ErsatzRyan

+0

Esto pasa, así que sí lo 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

¿Hay alguna razón por la cual necesite usar ID de usuario como clave externa? ¿Por qué no usar la clave principal del campo asociado? – jonnii

Respuesta

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

gracias, pero mi ID es id. Sin embargo, para esta asociación quiero usar una columna diferente –

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 clase como la que afecta solo al controlador actual o todas las acciones). Aún así, es solo lo que considero una solución.

1

Aquí están pasando dos cosas. Creo que ha cambiado las declaraciones: has_one y: belongs_to.

El :belongs_to viene en el modelo que tiene la clave externa. El :has_one viene en el modelo al que se hace referencia (si es solo uno, de lo contrario, si hay muchas filas: pertenece_al igual, es un has_many, por supuesto). Para obtener más información, lea here.

Primero, deberá especificar (anular) la clave principal del modelo. Aquí estoy suponiendo que un usuario puede tener muchos tweets en lugar de uno solo (de lo contrario, reemplace por :has_one).

class UserProfile 
    set_primary_key :userid 
    has_many :tweets 
end 

entonces usted necesita ajustar su declaración :has_one:

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

Luego, en segundo lugar, una vez que sus relaciones están configurados correctamente, no hay necesidad de asignar tanto :user_profile o :userid en tiempo de creación. O crea un nuevo UserProfile y las claves foráneas se corregirán automáticamente o asignará un userid de un perfil existente.

Espero que esto ayude.

Cuestiones relacionadas