Trying to display data from two tables


#1

Alrighty folks, I’m really trying here, and want to succeed with Ruby on
Rails.

I’m trying to display data that is linked from two tables using the
Active Record naming conventions, as described in Agile Web book.

The stripped-down basics;

Database

drop table if exists people;
CREATE TABLE people (
id int(6) NOT NULL auto_increment,
lastname varchar(30) NOT NULL,
personkind_id int(6) NOT NULL default ‘23’,
PRIMARY KEY (id)
)

drop table if exists person_kinds;
CREATE TABLE person_kinds (
id int(6) NOT NULL auto_increment,
kind varchar(30) NOT NULL,
PRIMARY KEY (id)
)

###########################

Using ruby script/generate scaffold

Controllers;

class PersonAdminController < ApplicationController

def list
@person_pages, @people = paginate(:people, :order_by =>‘lastname’,
:per_page => 10)
@person_kinds = PersonKind.find_all
end

class PersonKindAdminController < ApplicationController

###########################

Models

class Person < ActiveRecord::Base
belongs_to :person_kind
end

class PersonKind < ActiveRecord::Base
has_many :people
end

###########################

list.rhtml

People by Field

<% @people.each do |person| %>

<% end %>

Last Name

Kind

<%= link_to person.lastname, :action => "show", :id => person.id %> <%= person.firstname %> <%= person.person_kind.kind %>

<%= link_to "Add New Person", :action => "new" %>

##############################

The <%= person.person_kind.kind %> line in the list.rhtml is what is
causing my brain to turn to tapioca.

I really thought that that would work. I know this is very basic Rails
stuff, but I’m stuck. Any help would be greatly appreciated.

Kindest regards.


#2

Andy P. wrote:

def list
@person_pages, @people = paginate(:people, :order_by =>‘lastname’,
:per_page => 10)
@person_kinds = PersonKind.find_all
end

try adding an :include=>:kind to the paginate function.


#3

Kevin O. wrote:

try adding an :include=>:kind to the paginate function.

Nope it generates the following erorr

“Association was not found; perhaps you misspelled it? You specified
:include => :kind”

If I just use

<%= person.person_kind.kind %>

in the list.rhtml, as in my first post, I get the following erorr,

“You have a nil object when you didn’t expect it!
The error occured while evaluating nil.kind”

I thought that the belongs_to & has_many took care of this.


#4

It looks like you are missing an underbar. Try ‘person_kind_id’ as the
column name in people.

Andy P. wrote:

Database

drop table if exists people;
CREATE TABLE people (
id int(6) NOT NULL auto_increment,
lastname varchar(30) NOT NULL,
personkind_id int(6) NOT NULL default ‘23’,
PRIMARY KEY (id)
)

drop table if exists person_kinds;
CREATE TABLE person_kinds (
id int(6) NOT NULL auto_increment,
kind varchar(30) NOT NULL,
PRIMARY KEY (id)
)


#5

Your code example works because it has nothing to do with how
ActiveRecord guesses names. AR uses the convention of adding _id to a
model name to get the foreign key. On the one hand you have a model
named “person_kind”, but on the other you are using the name
“personkind_id” for the foreign key. You should have a fk called
“person_kind_id” to follow AR’s convention, or explicitly specify the
non-standard foreign key in the association method in your model class
with :foreign_key => “personkind_id”

Andy P. wrote:
I thought this as well, however, the following works just fine on my

edit.rhtml

<% @person_kinds.each do |personkind| %> > <%= personkind.kind %> <% end %>

Although, I should try ‘person_kind_id’ as the column name just to rule
it out.


#6

joshua wrote:

It looks like you are missing an underbar. Try ‘person_kind_id’ as the
column name in people.

I thought this as well, however, the following works just fine on my
edit.rhtml

<% @person_kinds.each do |personkind| %> > <%= personkind.kind %> <% end %>

Although, I should try ‘person_kind_id’ as the column name just to rule
it out.

Thanks for taking the time to look at it.


#7

Andy P. wrote:

Database

drop table if exists people;
CREATE TABLE people (
id int(6) NOT NULL auto_increment,
lastname varchar(30) NOT NULL,
personkind_id int(6) NOT NULL default ‘23’,
PRIMARY KEY (id)
)

drop table if exists person_kinds;
CREATE TABLE person_kinds (
id int(6) NOT NULL auto_increment,
kind varchar(30) NOT NULL,
PRIMARY KEY (id)
)

###########################

I have to agree with Joshua on this. It seems as if the issue lies in
the foreign key name. I would definitely try renaming ‘personkind_id’
to ‘person_kind_id’ so that AR can find the link between the two tables.
Furthermore, check out page 230 in the Agile Web book. It gives some
good info on how AR actually creates methods for you based on table
relationships.

So for example, if you used the find() method to find all of the people
in your DB, you could get the data (attributes) related to each person
from the other table. I’m not really sure what your app is about but AR
can handle all of this for you based on the proper naming of the foreign
key, just double check page 230 in the book.


#8

richard downe wrote:

I have to agree with Joshua on this. It seems as if the issue lies in
the foreign key name. I would definitely try renaming ‘personkind_id’
to ‘person_kind_id’ so that AR can find the link between the two tables.
Furthermore, check out page 230 in the Agile Web book. It gives some
good info on how AR actually creates methods for you based on table
relationships.

So for example, if you used the find() method to find all of the people
in your DB, you could get the data (attributes) related to each person
from the other table. I’m not really sure what your app is about but AR
can handle all of this for you based on the proper naming of the foreign
key, just double check page 230 in the book.

I’ll check page 230 first thing in the morning, thankyou Richard.

I made the assumption that the selection box was using Active Record in
the same manner.


#9

joshua wrote:

Your code example works because it has nothing to do with how
ActiveRecord guesses names. AR uses the convention of adding _id to a
model name to get the foreign key. On the one hand you have a model
named “person_kind”, but on the other you are using the name
“personkind_id” for the foreign key. You should have a fk called
“person_kind_id” to follow AR’s convention, or explicitly specify the
non-standard foreign key in the association method in your model class
with :foreign_key => “personkind_id”

Joshua,

Spot on mate. Thankyou so much.

Changing “personkind_id” to “person_kind_id” solved the problem.

Also, thankyou for taking the time explaining why the selection box
would work.

Once I made that change, I also had to change my selection box too

<% @person_kinds.each do |person_kind| %> > <%= person_kind.kind %> <% end %>