SitePoint Sponsor |
|
User Tag List
Results 1 to 14 of 14
Thread: Saving data to two tables
-
Mar 2, 2006, 23:31 #1
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Saving data to two tables
I am trying to save data to two tables - person and address. But first I want to do a lookup on the address table to make sure that the address entered does not already exist in the address table - if it does I want to extract the residence.id and plug that into the person table. Otherwise, I will just save the data to the respective tables. Here is the code I have tried thus far:
Code:def create # this part of the code does not work because I haven't a clue what I am doing @address_check = Residence.find(params[:residence]) #check for an existing address @person = Person.new(params[:person]) if @address_check @person.residence_id = @address_check.id if @person.save flash[:notice] = 'The Person was successfully created.' redirect_to :action => 'list' else render :action => 'new' end else #this part of the code works @residence = Residence.new(params[:residence]) if @person.save && @residence.save @person.update_attribute(:residence_id, @residence.id) flash[:notice] = 'The person was successfully created.' redirect_to :action => 'list' else render :action => 'new' end end end
Rick
-
Mar 3, 2006, 06:57 #2
The plugging in of your residence id into your person model should be handled by Rails associations.
I'm not sure how you are determining if an address already exists (Residence.find(params[:residence]) wont work) but lets say you have a house_number and a postcode field, which would be a good way of identifying a unique address.
It seems to me you want something like:
Code:# residence.rb class Residence has_one :person # could be has_many end # person.rb class Person belongs_to :residence end # your controller def create # will load an existing address if it exists, else create a new one residence = Residence.find_or_create_by_house_number_and_postcode(params[:residence][:house_number], params[:residence][:postcode]) person = residence.build_person(params[:person]) if person.save and residence.save flash[:notice] = 'The person was created successfully' redirect_to :action => 'list' else redirect_to :action => 'new' end end
See the following API docs for more details:
http://api.rubyonrails.com/classes/A...cord/Base.html
http://api.rubyonrails.com/classes/A...ssMethods.html
-
Mar 3, 2006, 11:02 #3
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Luke,
Thanks for that - I will give it a try. I had a look at the API references but I must admit it will take some time before I get it (that is understand just what is going on). For example, just what does this mean:Code:residence = Residence.find_or_create_by_house_number_and_postcode(params[:residence][:house_number], params[:residence][:postcode])
Code:residence = Residence.find_or_create_by_house_number_and_postcode_and_aptnum(params[:residence][:house_number], params[:residence][:postcode] params[:residence][:aptnum])
Sorry for that - I found the answer by reading the documentation - Dynamic attribute-based finders. But I am still puzzeled by the second statement.
I believe I will have to check for the aptnum also because people in an apt all live at the same address and postalcode but different apts. Should I expect any problems with nil apt numbers.
Finally, I found the syntax in the API docs but what does this line of code do exactly:Code:person = residence.build_person(params[:person])
Thanks for your patience.
Rick
-
Mar 3, 2006, 11:17 #4
The first code breaks down into two parts.
First, find_or_create will return a matching record if it exists or a new record if it doesn't.
Rails supports dynamic name based finders so yes, you could add aptnum in exactly the way you did above.
See "Dynamic attribute-based finders" here:
http://api.rubyonrails.com/classes/A...cord/Base.html
The last method, build_person is a dynamically create method available due to the association made between people and residences. residence.build_person() creates a new Person object that is automatically linked to the residence object you call it on - it creates the link for you. build_person() returns the new person object without saving it. There is also create_person() which does save the associated record.
See the associations API and look under each association type for the methods it makes available to your objects:
http://api.rubyonrails.com/classes/A...ssMethods.html
-
Mar 3, 2006, 16:12 #5
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Thanks Luke for your time and knowledge. The more I find out about ror the more I like it.
Rick
-
Mar 4, 2006, 00:55 #6
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Luke,
I tried your example code and received the following error: undefined method `find_or_create_by_number_and_aptnum_and_postcode' for Residence:Class
Any idea what generates this error?
Rick
-
Mar 4, 2006, 06:15 #7
Does your residences table have the columns 'number', 'aptnum' and 'postcode'?
-
Mar 4, 2006, 09:58 #8
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
It does now - I completely missed postcode - should have been postalcode. Must have checked it a dozen or more time but couldn't see the forest. Now the following statement
Code:person = residence.build_person(params[:person])
Rick
-
Mar 4, 2006, 10:31 #9
It should be
Code:has_many :people
-
Mar 4, 2006, 10:50 #10
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I tried that and it did not work either. It threw the same error. Here is what I have:
Code:class Residence < ActiveRecord::Base has_many :people #I assume this has to be plural to fit with has_many end class Person < ActiveRecord::Base belongs_to :residence end # and the line that is throwing the error person = residence.build_person(params[:person])
Rick
-
Mar 4, 2006, 15:12 #11
Mmm, should work. What version of Rails are you using?
Try residence.people.build() or residence.build_people()
-
Mar 4, 2006, 17:16 #12
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Well Luke,
I have had mixed success. I did get the record to post to the db and everything looks correct at first blush. The code I used wasCode:people = residence.people.build(params[:people])
Then when it wast to return to the list view I started getting the following error:You have a nil object when you didn't expect it!
The error occured while evaluating nil.aptnum
and the ofending line of code is:Code:<%=h list_stripes.residence.aptnum.nil? ? ' ' : ('Apt.' + list_stripes.residence.aptnum + ' - ') %>
What would be the cause of this error?
Rick
-
Mar 4, 2006, 17:42 #13
In fact, the error means that list_stripes.residence is returning a nil object (of NilClass) rather than a Residence object, and you are trying to call the method aptnum() on nil, which of course doesn't exist.
So you need to look at why list_stripes.residence is retruning nil. What is list_stripes?
-
Mar 4, 2006, 19:12 #14
- Join Date
- Nov 2004
- Location
- Victoria BC
- Posts
- 116
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
list_stripes is just a helper to alternately color the rows of a table. I did find the problem - I had one row in my person table thad did not have a corresponding row in the residence table. Fixed it and problem solved.
Finally, how do you show an email image with an address attached to it. I have tried numerous mail_to and image_tag variations but just can't seem to figure it out.
RickLast edited by ricklach; Mar 5, 2006 at 05:55.
Bookmarks