0

I have three models that I want to interact with each other.

Kase, Person and and Company.

I have (I think) setup the relationships correctly:

class Kase < ActiveRecord::Base
#HAS ONE COMPANY
has_one :company

#HAS MANY PERSONS
has_many :persons


class Person < ActiveRecord::Base
belongs_to :company

class Company < ActiveRecord::Base
has_many :persons
def to_s; companyname; end

I have put the select field on the create new Kase view, and the create new Person view as follows:

<li>Company<span><%= f.select :company_id, Company.all %> </span></li>

All of the above successfully shows a drop down menu dynamically populated with the company names within Companies.

What I am trying to do is display the contact of the Company record within the kase and person show.html.erb.

For example, If I have a company called "Acme, Inc." and create a new Kase called "Random Case" and choose within the create new case page "Acme, Inc." from the companies drop down menu. I would then want to display "Acme, Inc" along with "Acme, Inc. Mobile" etc. on the "Random Case" show.html.erb.

I hope this makes sense to somebody!

Thanks,

Danny

EDIT: kases_controller

def show
@kase = Kase.find(params[:id])

respond_to do |format|
  format.html # show.html.erb
  format.xml  { render :xml => @kase }
  format.pdf { render :layout => false }

  prawnto :prawn => { 
             :background => "#{RAILS_ROOT}/public/images/jobsheet.png",

             :left_margin => 0, 
             :right_margin => 0, 
             :top_margin => 0, 
             :bottom_margin => 0, 
             :page_size => 'A4' }
end   end
dannymcc
  • 3,744
  • 12
  • 52
  • 85

2 Answers2

3

I think your model associations are incomplete based on what you've posted in your question:

class Kase < ActiveRecord::Base
  has_one :company
  has_many :people # Rails should handle the correct plural here
end

class Company < ActiveRecord::Base
  has_many :people
  belongs_to :kase
end

class Person < ActiveRecord::Base
  belongs_to :company
  belongs_to :kase
end

With the assocations set up correctly, you can then access a company's attributes for a given case:

kase.company.name
kase.company.mobile

—or for a given person:

person.company.name
person.company.mobile

You can even get to the company via a person's case:

person.kase.company.name # etc...
John Topley
  • 113,588
  • 46
  • 195
  • 237
  • Great, I have made those changes and will try calling the attributes now. – dannymcc Apr 26 '10 at 15:49
  • Obviously I guessed what your model attributes are called, so you need to use the correct names as defined in your database migrations. – John Topley Apr 26 '10 at 15:51
  • If I add the following:
  • Company: <%=h @kase.company.companyname %>
  • I get the following error: NoMethodError in Kases#show Showing app/views/kases/show.html.erb where line #14 raised: You have a nil object when you didn't expect it! The error occurred while evaluating nil.companyname Any idea what I am doing wrong? Thanks, Danny – dannymcc Apr 26 '10 at 16:31
  • I'm assuming that you actually have some cases with an associated company in your database, right? Can you edit your question to show us the `show` action within your `KasesController`. – John Topley Apr 26 '10 at 17:38
  • OK, so for some reason Rails is saying that your @kase instance doesn't have a company associated with it. Can you try running the Rails console (`script/console`) and finding a kase that you know has an associated company and then seeing what `kase.company` returns? – John Topley Apr 26 '10 at 19:19
  • Here is a screenshot of the database: http://img.skitch.com/20100426-pyi8uqks8ajs4mbjm43xe24gqn.jpg The database is purely in development so there are only two test cases/kases. Both are showing a company in the company id field. – dannymcc Apr 26 '10 at 19:33
  • Where does that `company_id` field in your screenshot come from? Is it an actual column within your `kases` table, or is it as a result of executing a query? – John Topley Apr 26 '10 at 19:41
  • That's actually a column within the kases table. Sorry if I'm doing something wrong - I'm really new to RoR – dannymcc Apr 26 '10 at 19:50
  • If it helps, the whole application is on my Github page: http://github.com/dannyweb/surveycontrol – dannymcc Apr 26 '10 at 19:56
  • I'll try to take a look at it tomorrow. – John Topley Apr 26 '10 at 20:55
  • Looking at your controller code on GitHub, it looks like you're just creating the individual model instances and not creating associations between them, which means that the foreign keys don't get set in the database. Have a look at sections 4.1, 4.3.1.12 and 4.3.1.13 in http://guides.rubyonrails.org/association_basics.html – John Topley Apr 27 '10 at 07:03
  • Thanks John. I have read through those sections, to be honest I think they have confused me a little. From my understanding; I have added the has_many and belongs_to etc. to the relevant controllers. This is based on one of the examples on the Rails Wiki: class Supplier < ActiveRecord::Base has_one :account, :include => :representative end class Account < ActiveRecord::Base belongs_to :supplier belongs_to :representative end class Representative < ActiveRecord::Base has_many :accounts end Do I also need to add the class_names etc? Thanks, Danny – dannymcc Apr 27 '10 at 08:28
  • @Danny, the structural relationships between your models are fine. The problem is that when your models are created and saved in your controllers when your app runs, you're not also setting the associations. Effectively your model instances are lonely islands with no relationships to other models. So the foreign keys never get set in the database. Look at this http://guides.rubyonrails.org/getting_started.html#generating-a-controller in particular the line `@comment = @post.comments.build(params[:comment]` in the `new` action of the `CommentsController`. – John Topley Apr 27 '10 at 09:28
  • ahh, ok that helps a little. So for my new kase def it would be something like this:? @kase = @company.kaseid.build For the project I am working on, its purely for me to try and learn Rails, would you be interested in getting this working for me with comments in the code and charging me for your time? Thanks, Danny – dannymcc Apr 27 '10 at 09:37
  • That's on the right track, yes. Or you can use `create` instead of `build` to have the association created and saved to the database in one step. I appreciate your offer, but unfortunately I don't have a lot of free time at the moment. I think you'd probably get a better return for your money anyway by buying some or all of these screencasts: http://pragprog.com/screencasts/v-rbar/everyday-active-record PeepCode have many great Rails screencasts too: http://peepcode.com/ And continue to ask questions here! I wish Stack Overflow had been around when I was first learning Rails. – John Topley Apr 27 '10 at 09:49
  • Ok, thank you anyway. I do really appreciate your time though! So if I had: @kase = @company.kaseid.create in my kase controller, is that saying when a new Kase is created, add the kaseid to the company model? I think this is the bit I dont understand. What that line is actually going to do. Thanks, Danny – dannymcc Apr 27 '10 at 09:54
  • It should be `@kase = @company.kases.create(params[:kase])` All it does is create a new case through the association i.e. add the new case to the company's existing collection of cases and save it to the database all in one hit. In database terms, it sets the `kase_id` column for that company record to the ID of the case record that owns it. The `params[:kase]` bit is a bit of Rails' magic that sets the attributes of the new case to the values from the submitted form. You can test it from the Rails console if you want: `@kase = @company.kases.create(:jobno => 'foo', :clientref => 'bar' etc.)` – John Topley Apr 27 '10 at 10:08
  • Does that mean that the way I have it currently, each company can only have one case/Kase? – dannymcc Apr 27 '10 at 10:31
  • You have declared a one-to-one relationship between case and company. – John Topley Apr 27 '10 at 10:35
  • Hmm, I'm unsure what I need to declare as each case only has one company but each company will have multiple cases. So should the case belong_to company and company has_many cases? – dannymcc Apr 27 '10 at 10:39
  • Ok, I have made all of the relevant changes to the models (I think!) and added the params line as above to kase_controller but I get the following error: NoMethodError in KasesController#new You have a nil object when you didn't expect it! The error occurred while evaluating nil.kases – dannymcc Apr 27 '10 at 11:00
  • I'm sorry Danny, I can't spend any more time helping you on this at the moment. My advice is to get yourself a good Rails book or the ActiveRecord screencasts I mentioned earlier. Good luck! – John Topley Apr 27 '10 at 11:05
  • No problem, I am buying those screencasts as we speak! Thanks for your help, very much appreciated! – dannymcc Apr 27 '10 at 11:07