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