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 Gill <jonathan.gill@securecirt.com> wrote:> > 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) > endBut 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) > endThis 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.> > 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 > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060803/e8031d4f/attachment.html
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 > endNaming convention change:> class OperatingSystem < ActiveRecord::Base # change from Operatingsystem > has_many :hosts > endAgain, we''re throwing out the habtm for the time being:> class Software < ActiveRecord::Base > set_table_name "software" #not softwares! > endNow 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 OSNow there is :) 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
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