Hi all,
Another newb online… trying belongs_to and has_one constructs for
the first time.
table Location defined as:
nickname, street, city, … , contact_id
the model includes “belongs_to :contact”
table Contact defined as:
name, title, … , location_id
the model includes “has_one :location”
When I build a list_contacts view, I assume
h(contact.location.nickname) will make the connection. However Rails
returns nil for contact.location. (Verified the linkage is present,
thanks to script/console.) Seems like I’m missing something very
simple, but I’m stumped. Ideas?
Best,
Brian
Austin, Texas
[email protected] wrote:
When I build a list_contacts view, I assume
h(contact.location.nickname) will make the connection. However Rails
returns nil for contact.location. (Verified the linkage is present,
thanks to script/console.) Seems like I’m missing something very
simple, but I’m stumped. Ideas?
Best,
Brian
Austin, Texas
Can you post your controller code for list_contacts? If you have
‘dereferenced’ your scaffold code also make sure you have an instance
variable that holds the information for your contact in the controller
or else your view wont have anything to display.
Also, maybe you just left this out, but contact.location is nil but is
just contact nil also?
Lastly, your table should be named w/ pluralizes names.
Ex: ‘create table Contacts …’ and ‘create table Locations…’ not the
singular version you posted in your original mail. Remember models are
singular and the db tables they are tied to are pluralized.
I’ll assume that you posted just pseudo code but I had to mention it
just in case.
Hope this, at the least, kicks off a direction for a solution to your
problem.
Hello Jean,
I appreciate the reply. As requested:
controller:
def list_contacts
@contact_pages = Paginator.new self, Contact.count, 60, params[:page]
@contacts = Contact.find :all, :order => params[‘order’] ||
‘lastname’,
:limit => @contact_pages.items_per_page,
:offset => @contact_pages.current.offset
end
view:
… various html …
<% for contact in @contacts
# location = Location.find(contact.location_id)
%>
<%= link_to h(contact.lastname+‘,’+contact.firstname), :action
=> ‘edit_contact’, :id => contact.id %>
<%= h(contact.title) %>
<%= h(contact.email1) %>
<%= h(contact.phone1) %>
<%= h(contact.location.nickname) %>
… various html …
<% end %>
Notice the "Location.find(contact.location_id) … this works…
Tks again…
Brian
On Jul 24, 12:02 am, Jean N. [email protected]
Chris wrote:
Option 1:
contacts = Contact.find(:all)
Each call to c.location triggers a DB query to delay load the
location for that contact
contacts.each { |c| c.location.nickname }
Option 2:
contacts = Contact.find(:all, :includes => [:location])
All locations are loaded upfront, so there is only ever 1 DB call
contacts.each { |c| c.location.nickname }
Cheers,
Chris
On Jul 24, 3:02 pm, Jean N. [email protected]
Adding to this, remove any DB calls in your view. this breaks the model
/ view/ controller architecture as you’re having a view interact
directly WITH the Database.
Encapsulate ALL ‘business logic / use cases’ and database access in your
controller and let your view determine how all the data ‘sent’ to it is
displayed. Even using a loop and querying the db for your location,
although a minor infraction, is considered logic and not display.
You have 2 columns locations.contact_id and contacts.location_id. Of
these, only locations.contact_id is used by the associations you have
defined.
class Location < AR::Base
This will lookup locations.contact_id to find the association
belongs_to :contact
end
class Contact < AR::Base
This will also lookup locations.contact_id to find the association
has_one :location
end
Make sure that locations.contact_id is populated in your DB, and that
you haven’t mistakenly populated contacts.location_id instead.
BTW, if you need to query a list of contacts, think about the
performance of using associations.
Option 1:
contacts = Contact.find(:all)
Each call to c.location triggers a DB query to delay load the
location for that contact
contacts.each { |c| c.location.nickname }
Option 2:
contacts = Contact.find(:all, :includes => [:location])
All locations are loaded upfront, so there is only ever 1 DB call
contacts.each { |c| c.location.nickname }
Cheers,
Chris
On Jul 24, 3:02 pm, Jean N. [email protected]