One-to-One relationships with Rails

This is a lot easier than I thought it would be and it actually took me longer than it should have because I was trying to do it manually.

First you need to define the relationship on the parent and children models:

  1. <br />
  2. class Person < ActiveRecord::Base<br />
  3. has_one :person_details, :dependent=>true<br />
  4. end</p>
  5. <p>class PersonDetails < ActiveRecord::Base<br />
  6. belongs_to :person<br />
  7. end</p>
  8. <p>

Note that this automatically will provide with a person_details member for person when it gets retrieved.

Now on the controller, here's the CRUD:

  1. <br />
  2. def create<br />
  3. @person = Person.new(params[:person])<br />
  4. @person_details = PersonDetails.new(params[:person_details])<br />
  5. @person.person_details = @person_details<br />
  6. if @person.save<br />
  7. # Cool, you're done! It saves the person_details as well.<br />
  8. end<br />
  9. end</p>
  10. <p> def edit<br />
  11. @person = Person.find(params[:id])<br />
  12. @person_details = @person.person_details<br />
  13. end</p>
  14. <p>def update<br />
  15. @person = Person.find(params[:id])<br />
  16. if @person.update_attributes(params[:person]) and<br />
  17. @person.person_details.update_attributes(params[:person_details])<br />
  18. # Cool, you're done!<br />
  19. end<br />
  20. end</p>
  21. <p>def destroy<br />
  22. Person.find(params[:id]).destroy<br />
  23. end<br />
  24.  

Now your rhtml _form.rhtml must have things like:

  1. <br />
  2. text_field 'person_details', column.name<br />
  3. text_field 'person, column.name<br />
  4.  

And you will get two sets of parameters (as you can see in your controller code), params[:person], and params[:person_details]. Your instance variables to set the current values on the view side would be @person and @person_details.

And I was sitting there writing custom code to find/save.. Ugh!

Be Sociable, Share!

1 Comment

russellNovember 25th, 2008 at 12:30 am

On edit if you want to save 2 database calls you can put
@person = Person.find(params[:id], :include =>:person_details)

Leave a comment

Your comment