Why is my models can't be related using has_one and belongs_to?

Dear all, This is a repost of my question, because the first post is considered as thread hijack. I hope i got this right this time.

I have a silly problem in setting up a relationship between 4 models.

I set these 4 models, ComUser, DefJabatan, DefUserRole, DefKelamin. In each model with name started with 'Def', i put a has_one:ComUser relationship. So naturally i have 3 belongs_to relationship in ComUser. I do a simple query in the controller: @users = ComUser.find(:first) and in the view, i simply put a object debug: <%=debug(@users)%>

and I get this:

--- !ruby/object:ComUser attributes:   def_jabatan_id: "1"   created_at: 2010-11-16 04:31:35   def_user_role_id: "1"   gsm: "-"   updated_at: 2010-11-16 04:31:35   alamat: "-"   username: admin   id: "1"   def_kelamin_id: "1"   password: admin   online_status: "2" attributes_cache: {}

I'm getting a feeling that I didn't set the relationship right, because i don't see any attributes addition in the ComUser from the model started with Def-something that i create above..

Am I missing something here, like violating a naming convention or something?

I even tries to alter the table by implicitly put a foreign key in the table for ComUser model using sql statements, and the debug result is still the same. How can i make this relationship work?

Thanks

PS. I put the code snippet that i use for migrating the database and defining the relationship below.

Regards, Arga

ComUser < ActiveRecord::Base   belongs_to :DefKelamin   belongs_to :DefUserRole   belongs_to :DefJabatan Migration:     create_table :com_users do |t|     t.timestamps     t.references :def_jabatan, :null => false     t.integer :def_kelamin_id, :null => false     t.references :def_user_role, :null => false     t.column :username,'varchar(20)', :null => false     t.column :password,'varchar(20)', :null => false     end

DefJabatan < ActiveRecord::Base   has_one:ComUser Migration:     create_table :def_jabatans do |t|     t.timestamps     t.column :jabatan,'varchar(20)', :null => false     end

DefUserRole < ActiveRecord::Base   has_one:ComUser Migration:     create_table :def_user_roles do |t|     t.timestamps     t.column :role,'varchar(20)', :null => false     t.string :description, :null => false     t.string :icon     end

DefKelamin < ActiveRecord::Base     has_one :ComUser Migration:     create_table :def_kelamins do |t|     t.timestamps     t.column :kelamin,'varchar(10)', :null => false     end

When you specify the association with "has_one" or "belongs_to", you should be using lowercase_underscore instead of CamelCase.

For example:

"has_one :ComUser" should be "has_one :com_user" "belongs_to :DefKelamin" should be "belongs_to :def_kelamin"

Hello Tim,

I have done that, and sadly still got this from the debug:

--- !ruby/object:ComUser attributes:   def_jabatan_id: "1"   created_at: 2010-11-16 04:31:35   def_user_role_id: "1"   gsm: "-"   updated_at: 2010-11-16 04:31:35   alamat: "-"   username: admin   id: "1"   def_kelamin_id: "1"   password: admin   online_status: "2" attributes_cache: {} Restarting mongrel does not help. Debug still returns the same thing, without any relationship that can be seen.

regards,

Arga

Am I missing something here, like violating a naming convention or something?

When you specify the association with "has_one" or "belongs_to", you should be using lowercase_underscore instead of CamelCase.

For example:

"has_one :ComUser" should be "has_one :com_user" "belongs_to :DefKelamin" should be "belongs_to :def_kelamin"

Forgot to add that changing the case on the association won't fix this.

Using the debug helper simply calls to_yaml on the model, which won't show any of the associations. It simply shows the foreign keys: def_jabatan_id, def_kelamin_id, etc.

If debug can't be used for checking relationship, how can I check whether the relationship is already up and running? I have tried to_yaml and inspect, but to_yaml (simple_format @users.to_yaml) returns the same thing as debug, @users.inspect returns #

I have tried to access the attribute of the def-something model directly in the controller, but it gave me an error stated that the object does not that attributes. From what i understand from this, my relationship setup is still failed. I also have tried to change the involved objects to something like def_jabatan, defjabatan, etc in all of the model files, but it still does not work.

regards, Arga

arga aridarma wrote in post #961823:

If debug can't be used for checking relationship, how can I check whether the relationship is already up and running?

With your automated tests. reflect_on_association should get you started.

(If you don't have comprehensive automated tests, write them now, before you write any more application code.)

Best,

Thanks for the advice. I have tried to check with the reflections, and surely enough the relation is there. So i tried to change the query in the controller to this:

@users = ComUser.find(:first, :include =>[:def_jabatan,:def_kelamin,:def_user_role])

and finally the debug shows more attributes, and i can do something like @a = @users.def_jabatan.jabatan :smiley:

Is this the correct way to get the relationship data, that is by adding ":include" in the search, or is there's more elegant way to do it?

You should not need the :include. What happens if you run the above code without the :include?

Colin

Without include, the debug return this:

--- !ruby/object:ComUser attributes:   def_jabatan_id: "3"   created_at: 2010-11-16 04:31:35   def_user_role_id: "1"   gsm: "-"   updated_at: 2010-11-16 04:31:35   alamat: "-"   username: admin   id: "1"   def_kelamin_id: "1"   password: admin   online_status: "2" attributes_cache: {} but with include, the debug return this:

--- !ruby/object:ComUser attributes:   def_jabatan_id: "3"   created_at: 2010-11-16 04:31:35   def_user_role_id: "1"   gsm: "-"   updated_at: 2010-11-16 04:31:35   alamat: "-"   username: admin   id: "1"   def_kelamin_id: "1"   password: admin   online_status: "2" attributes_cache: {}

def_jabatan: !ruby/object:DefJabatan   attributes:     def_jabatan_id: "3"     created_at: 2010-11-16 04:31:38     updated_at: 2010-11-16 04:31:38     jabatan: Dokter Gigi     id: "3"   attributes_cache: {}

def_kelamin: !ruby/object:DefKelamin   attributes:     created_at: 2010-11-16 04:31:38     updated_at: 2010-11-16 04:31:38     id: "1"     kelamin: Wanita   attributes_cache: {}

def_user_role: !ruby/object:DefUserRole   attributes:     created_at: 2010-11-16 04:31:40     updated_at: 2010-11-16 04:31:40     role: admin     id: "1"     icon: ""     description: Administrator   attributes_cache: {}

With include, i'm able to access the related data. The last 3 objects are the data that related to the first one in the model, using has_one and belongs_to

regards, Arga

Please don't top post, it makes it difficult to follow the thread

Without include, the debug return this:

--- !ruby/object:ComUser attributes: def_jabatan_id: "3" created_at: 2010-11-16 04:31:35 def_user_role_id: "1" gsm: "-" updated_at: 2010-11-16 04:31:35 alamat: "-" username: admin id: "1" def_kelamin_id: "1" password: admin online_status: "2" attributes_cache: {} but with include, the debug return this:

--- !ruby/object:ComUser attributes: def_jabatan_id: "3" created_at: 2010-11-16 04:31:35 def_user_role_id: "1" gsm: "-" updated_at: 2010-11-16 04:31:35 alamat: "-" username: admin id: "1" def_kelamin_id: "1" password: admin online_status: "2" attributes_cache: {}

def_jabatan: !ruby/object:DefJabatan attributes: def_jabatan_id: "3" created_at: 2010-11-16 04:31:38 updated_at: 2010-11-16 04:31:38 jabatan: Dokter Gigi id: "3" attributes_cache: {}

def_kelamin: !ruby/object:DefKelamin attributes: created_at: 2010-11-16 04:31:38 updated_at: 2010-11-16 04:31:38 id: "1" kelamin: Wanita attributes_cache: {}

def_user_role: !ruby/object:DefUserRole attributes: created_at: 2010-11-16 04:31:40 updated_at: 2010-11-16 04:31:40 role: admin id: "1" icon: "" description: Administrator attributes_cache: {}

That is not what I asked, see below

With include, i'm able to access the related data. The last 3 objects are the data that related to the first one in the model, using has_one and belongs_to

regards, Arga

From: Colin Law <clanlaw@googlemail.com> To: rubyonrails-talk@googlegroups.com Sent: Tuesday, November 16, 2010 22:41:52 Subject: Re: [Rails] Re: Re: Why is my models can't be related using has_one and belongs_to?

Thanks for the advice. I have tried to check with the reflections, and surely enough the relation is there. So i tried to change the query in the controller to this:

@users = ComUser.find(:first, :include =>[:def_jabatan,:def_kelamin,:def_user_role])

and finally the debug shows more attributes, and i can do something like @a = @users.def_jabatan.jabatan :smiley:

Is this the correct way to get the relationship data, that is by adding ":include" in the search, or is there's more elegant way to do it?

You should not need the :include. What happens if you run the above code without the :include?

I asked what happens when you execute @user = ComUser.find(:first) @a = @user.def_jabatan.jabatan

Colin

belongs_to?

Please don't top post, it makes it difficult to follow the thread

Sorry.

I asked what happens when you execute @user = ComUser.find(:first) @a = @user.def_jabatan.jabatan

ok, by executing this, the debug of @user returns the ComUser object and also the related DefJabatan object. So it seems that i have to "access" the relationship manually rather than expecting that @user = ComUser.find(:first) will return the whole objects package, including all the related object. Am I correct?

regards, Arga

Without the include ComUser.find fetches just the ComUser object. When you then access @user.def_jabatan Rails realises that the DefJabatan object has not been read and so goes and gets it. It is not that you have to access the relationship manually in order to fetch it, it is that _if_ you access it then it will fetch it. Normally this is appropriate as it only fetches stuff that is required.

Colin

Thanks all for the help. It's quite clear to me now, relating this problem.

And sorry for the late reply, i was away for sometimes and there's a stockpile of emails flowing into my inbox :))

Regards

Arga