Relationships between models

Hi All,

I think Im having a mental block here. For some reason I just cant get
my head round relationships.

What I have is the following.

4 tables

  1. Hosts
  2. Software
  3. OperatingSystem
  4. Company

In my terms (which are most likely wrong) a company can have lots of
hosts, a host has lots of software, a host has one operating system.

So should my models have the following relations in them?

class Host < ActiveRecord::Base
belongs_to :customer
has_and_belongs_to_many :software
belongs_to :operatingsystems
end

class Customer < ActiveRecord::Base
has_many :hosts
end

class Operatingsystem < ActiveRecord::Base
has_many :hosts
end

class Software < ActiveRecord::Base
set_table_name “software” #not softwares!
has_and_belongs_to_many :hosts
end

The above seems to work, but I cant do things like
@hosts = Hosts.find(:all)
for host in @hosts
puts (host.operatingsystem.description)
end

as there doesnt seem to be a relationship between the host and the OS
(or software or customer) I have to do the following to get the OS (or
software or customer)

@host = Hosts.find(:all)
for host in @hosts
@os = Operatingsystem.find(host.id)
puts (@os.description)
end

Which is OK, but I think is not right somewhere.

Can someone point me to some good docs on this or tell me where I am
going wrong (ive read 4 days on rails, AWDWR etc)

Many thanks for the help

Jonathan

Hi Jonathan,

answers inline,

On 8/3/06, Jonathan G. [email protected] wrote:

  1. Software
    has_and_belongs_to_many :software

class Software < ActiveRecord::Base
set_table_name “software” #not softwares!
has_and_belongs_to_many :hosts
end

The above seems to work, but I cant do things like
@hosts = Hosts.find(:all)
for host in @hosts
puts (host.operatingsystem.description)
end

But this should work from your description of relationship in the
snips
above.

as there doesnt seem to be a relationship between the host and the OS

(or software or customer) I have to do the following to get the OS (or
software or customer)

@host = Hosts.find(:all)
for host in @hosts
@os = Operatingsystem.find(host.id)
puts (@os.description)
end

This shouldn’t work! At least it would find the right os just out of
coincidence. Because this would issue a select statement like SELECT *
from
operatingsystems WHERE id = [Your Host Id]. The line @os =
Operatingsystem.find_by_host_id(host.id) might work, but isn’t the
railish
way, IMHO.

I think that something is wrong in your underlying Schema that prevents
your
above mentioned host.operatingsystem.description from working.

What does your development log tell you by the way while issueing this
statement?

Cheers,
Jan

Which is OK, but I think is not right somewhere.

Actually, the only change you need to make to the OS stuff is to have
belongs_to :operatingsystem
in your Host model, rather than
belongs_to :operatingsystems

Drop the s on the end. But the fun part of your question is the habtm
=> deep model anyway.

Pat

Hey Jon,

I’m going to go through these individually, so hopefully you can see
my thought process. You’ve got the model pretty much down. The
biggest issue is that you’re not following the naming conventions, so
you’re getting unexpected (to you) behavior.

Using habtm isn’t really recommended anymore. It’s much better to set
up a full fledged model and use :through if you need to. I’m going to
take out the habtm for now, but we’ll get to it later.

class Host < ActiveRecord::Base
belongs_to :customer
belongs_to :operating_system # Note the change from :operatingsystems.
end

Customer is fine:

class Customer < ActiveRecord::Base
has_many :hosts
end

Naming convention change:

class OperatingSystem < ActiveRecord::Base # change from Operatingsystem
has_many :hosts
end

Again, we’re throwing out the habtm for the time being:

class Software < ActiveRecord::Base
set_table_name “software” #not softwares!
end

Now that we’ve made those changes, this code will work:

@hosts = Hosts.find(:all)
for host in @hosts
puts (host.operating_system.description) # note change from operatingsystem
end

as there doesnt seem to be a relationship between the host and the OS
Now there is :slight_smile: The issue there was that you weren’t following the
naming conventions. You can do some stuff to futz with it, like
setting :class_name and stuff, but it’s just easier to follow the
conventions and get the magic.

Okay, so getting back to the habtm stuff. You said that Software
habtm Hosts…which is true, but not very descriptive. You certainly
can’t do anything beyond setting up that minimal relationship. A more
appropriate description is to say that a Host has lots of Software
installed on it, and that Software can be installed on multiple Hosts.
We can extract a new model from that - Installation:

class Installation < ActiveRecord::Base
belongs_to :host
belongs_to :software
end

now your Software and Host classes will change to use that:

class Software < AR::Base
has_many :installations
has_many :hosts, :through => :installations # lets you call
software.hosts
end

class Host < AR::Base
has_many :installations
has_many :softwares, :through => :installations # lets you call
host.softwares
end

Now that you’ve got a real model, you can add more attributes as they
appear, such as when the software was installed, who authorized or
installed it, a license key, etc. You even gain advantages all the
way up to the controller layer where now you can use restful
controllers for your entire domain model.

Hope that helps some.

Pat