Has_many and belong_to association not working

I have two models. call.rb which has_many :visits and visit.rb which
belongs_to :call. After populating call from the form which then
shows all the parameters including the call.id I then make a visit
corresponding to the call. the form for the new visit creates a new
record ok and shows the input information except for I have it show me
the call_id which is the foreign key and it tells me that it is nill
when I look at the record in the ruby console. So it never associates
the visit with the corresponding call.
my call.rb is as follows

class Call < ActiveRecord::Base
ALL_FIELDS = %w(name address age area sex notes)
VALID_SEX = [“Male”, “Female”]
validates_presence_of :name, :address, :age, :area
validates_inclusion_of :sex,
:in => VALID_SEX,
:message => “must be male or female”
has_many :visits, :foreign_key => ‘call_id’

end
the visit.rb is as follows

class Visit < ActiveRecord::Base
belongs_to :call, :class_name => ‘Call’, :foreign_key => ‘call_id’
end

my CallsController is

class CallsController < ApplicationController

def index
@call = Call.find(:first, :order => ‘RANDOM()’)
end

def new
@call = Call.new
end

def create
@call = Call.new(params[:call])
if @call.save
flash[:notice] = “Call submission succeded”
render :action => ‘show’
else
render :action => ‘new’
end
end

def show
@call = Call.find(params[:id])
end
end

My visits controller is

class VisitsController < ApplicationController

def index
end

def show
@visit = Visit.find(params[:id])
end

def new
@visit = Visit.new
end

def create
@visit = Visit.new(params[:visit])
if @visit.save
flash[:notice] = “Visit submission succeded”
render :action => ‘show’
else
render :action => ‘new’
end
end

end
And my schema after migrations is
ActiveRecord::Schema.define(:version => 6) do

create_table “calls”, :force => true do |t|
t.string “name”
t.string “address”
t.string “age”
t.string “area”
t.date “date”
t.datetime “created_at”
t.datetime “updated_at”
t.string “sex”, :default => “Male”
t.text “notes”
end

create_table “visits”, :force => true do |t|
t.integer “call_id”
t.datetime “created_at”
t.datetime “updated_at”
t.string “name”
t.string “address”
t.date “date”
t.string “placement”
t.string “time_of_day”
t.text “topic”
t.text “next_topic”
end

end

Any help for a noob will be much greatly appreciated

“I think make a visit corresponding to the call” is a little
nebulous. How are you doing that?

Thanks for your reply

What is happening is that I create a call with a form from my new
action in my ViewsController and enter information such as name and
address. Then I execute the show action to view the entered data.
The show view then has a button which I click to create a visit for
that call (each call has_many visits). The show view for the call
controller does show also the call.id so I know it exists.
Then when the New action for the VisitsController is executed a new-
visit form is opened in which I enter information for the visit that
belongs_to that call. I enter information such as placement, topic
etc. then I execute the show action for the VisitsController and it
displays the information and the flash notice showing that the visit
was sucessfully created. I try to also display call_id which is the
foreign key for the visit but it displays nothing and when I check the
values for the visit record in the ruby console it tells me that the
value for call_id is nil. I hope this explains it better. This is my
first rails project so any help would be greatly appreciated.

Can you get the associations to work at the console?

FWIW–that foriegn_key arg on the has_many looks weird to me–it’s the
child tables that get FKs, not the parent. And at any rate, you’re
following the rails conventions there, so you shouldn’t have to specify
those explicitly (ditto on the :class_name arg).

Thanks for the reply

In fact I changed the models back to

class Call < ActiveRecord::Base
has_many :visits
ALL_FIELDS = %w(name address age area sex notes)
VALID_SEX = [“Male”, “Female”]
validates_presence_of :name, :address, :age, :area
validates_inclusion_of :sex,
:in => VALID_SEX,
:message => “must be male or female”

end

And

class Visit < ActiveRecord::Base
belongs_to :call
end

But the association does not work in the console
When I create a new visit from the show action link in my
calls.view.show.rhtml to new visit I go to the form for the
new visit and populate it with values. I try to display the call_id
and get nothing though it displays my other entered fieds. Then when
I go to the ruby console to check
the values of the new visit record the value of the foreign key
call_id is nil. So I am not
sure why this is so. When I do the show page from the call views I
display the call.id for
the call and it has the proper id but it never gets over to the
call_id column in the new
visit I make. The association doesn’t get the call_id. I am sorry
I,m such a noob but this is my first rails app I have all the books
and
have done a few screecasts but am stuck here
Thanks for your help

Well–let’s leave the views out of the picture for a sec. Can you do
something like:

my_call = Call.find(:first)
my_call.visits.count # <- we want one w/a count of 0
my_visit = Visit.find(:first)
my_call.visits < my_visit
my_call.save
my_call.visits.count # <- does this return ‘1’?
my_call.id == my_visit.call_id # <- do we get a ‘true’ here?

If that works, I think you can say your association is in fact working,
and we can start dissecting your views.

Dang it–that third line there should be

my_visit = Visit.find(:first)

Hello thanks again Here is what I get (I used the Visit with an id of
3 as the first couple had no data)

my_call.visits < my_visit
TypeError: compared with non class/module
from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/
associations/association_collection.rb:164:in <' from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/ associations/association_collection.rb:164:insend’
from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/
associations/association_collection.rb:164:in method_missing' from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/ base.rb:1693:inwith_scope’
from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/
associations/association_collection.rb:164:in send' from /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/ associations/association_collection.rb:164:inmethod_missing’
from (irb):10

So this is where I guess it falls apart
Thanks again Roy

Help please - does anyone have any other ideas on why I can’t get this
association to work?

LOL–more of my typos–sorry.

Make that

my_call.visits << my_visit

please.

Okay then–cool. And if I follow the earlier stuff, the view-mediated
Visit create process is not in question, right? It’s just the bit where
you create a Call from off a visits/show view? The resulting call does
not have the proper Visit reference? (And have you confirmed this by
looking in your db?)

If that’s all right–how are you kicking off the process of creating a
new Call from your visits/show view? I’m guessing a link_to call?
Let’s see that to start please.

Thanks Roy - Yes I do get a true after my_call.id==my_visit.call_id

Thanks again for the reply

Actually its the other way around each call has many visits and each
visit belongs to one call.
I create the call first and populate the form and it then shows me in
the ruby console
that all the fields are populated (the call.id, call.name,
call.address, etc)
Then what I try to do is create a new visit form that call (it has
further info and later I want to create new visits for that call)

On each calls.show.rhtml page I show some of what I entered and there
is link to create a new visit for that call that links to the new
action of the visits controller. This is where I want the association
to take place. It should take the call.id from the call and make it
the visits.call_id for that visit.

here is the views.calls.show.rhtml code

<%= @call.name %>

<%= @call.address %>

<%= @call.area %>

<%= @call.date %>

<%[email protected] %>
<%= link_to 'New Visit', :controller => "visits", :action => "new", :call_id => @call.id %>

<%= debug(params) %>

which opens a form for a New Visit

And here is the views.visits.new.rhtml

<%= error_messages_for ‘visit’ %>
<% form_for @visit do |f| %>

date:
<%= date_select ("post", "date") %>

placement:
<%= f.text_field :placement %>

time of day:
<%= f.text_field :time_of_day %>

topic:
<%= f.text_field :topic %>

next topic:
<%= f.text_field :next_topic%>

<%= f.submit "Create" %>

<%= debug(params) %>

<% end %>

When I check in the ruby console It show the record having been
populated except fot the visit.call_id which it records as nil. So it
is not getting the call.id from the call

Thanks again so much for your help

Ah, okay then. So this

<%= link_to ‘New Visit’,
:controller => “visits”,
:action => “new”,
:call_id => @call.id %>

Should bring us over to VisitsController.new(). I would expect that
code to look something like:

def new
@visit = Visit.new
@visit.call_id = params[:call_id] # <- is something like this line
here?
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @project }
end
end

How close is that?

I think you’re right. Your link_to call is passing the id of the
current call to your visit controller in a parameter called :call_id.
You can retrieve it out of the params hash in the same way that your
show method pulls :id out. But right now you’re not doing that. Try
adding this line under your @vist = Visit.new call:

@visit.call_id = params[:call_id]

Any better?

Cheers,

-Roy

Thank you again Roy. Actually Roy my whole visits controller is

class VisitsController < ApplicationController

def index
end

def show
@visit = Visit.find(params[:id])
end

def new
@visit = Visit.new
end

def create
@visit = Visit.new(params[:visit])
if @visit.save
flash[:notice] = “Visit submission succeded”
render :action => ‘show’
else
render :action => ‘new’
end
end

end

So this is most likely where I am having trouble

I’m sorry Roy I am not sure where to put that line - after @visit =
Visit.new in the new action of the VisitsController
or do I replace the new action with what you had above

def new
@visit = Visit.new
@visit.call_id = params[:call_id] # <- is something like this
line
here?
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @project }
end
end

Thanks again

Thanks again Roy. After I put it in the new action it looked like
this and i left off the xml stuff but it still didn’t pass the
call.id to the
call_id field in the visit. I can’t figure out why - maybe its the
link_to 'New Visit ’ line in my show view in my calls.views I don’t
know.

def new
@visit = Visit.new
@visit.call_id = params[:call_id]
end

Hmmm–so either we’re not getting a value in params[:call_id] or it’s
not making it into the visits/new form. Probably the former.

I’m sure there’s a better way to echo the contents of params to the
browser from a controller action (little help anyone?) but for now, can
you make this the first line in VisitsController.new:

raise(debug(params))

And let’s see what’s in that params hash…

Hello again Roy
I was wondering - does it make any difference that I use
render :action => ‘show’
rather than redirect_to :action => ‘show’ in the def create action?
Thanks again and again