Multiple Record Forms for Ruby on Rails

Posted on January 3, 2006
Filed Under General |

I have been experimenting with creating a new goal management application using Ruby on Rails. The first challenge has been creating a signup application that takes account information and account owner information and then updates both an account and an user model. I couldn’t find any examples on this that I could understand so I thought I would put up a short example of a working app.

First the database - two tables Accounts and Users

The Models

Account Model


class Account < ActiveRecord::Base
 has_many :users
 validates_presence_of :name
 validates_uniqueness_of :name
 validates_length_of :name, :maximum => 100
end

User Model


class User < ActiveRecord::Base
  belongs_to :account
  validates_presence_of :first_name, :last_name
  validates_uniqueness_of :first_name
end

The view


New account

<%= start_form_tag :action => ‘create’ %> <%= error_messages_for 'account' %>
<%= text_field 'account', 'name' %> <%= error_messages_for 'user' %>
<%= text_field 'user', 'first_name' %>
<%= text_field 'user', 'last_name' %> <%= submit_tag "Create" %> <%= end_form_tag %> <%= link_to 'Back', :action => ‘list’ %>

The controller - Signup


class SignupController < ApplicationController

  model :user
  model :account

  def index
    new
    render :action => ‘new’
  end

   def new
    @account = Account.new(@params['account'])
    @user= User.new(@params['yser'])
   end

  def create
    @account = Account.new(@params['account'])
    @user = User.new(@params['user'])
    @account.valid?
    @user.valid?
       if @account.valid? && @user.valid?
         name = @account.name
         @account.save
         @account = Account.find_by_name(name)
         @account.users << @user
         flash[:notice] = 'Account was successfully created.'
         redirect_to :action => ‘new’
      else
         render :action => ‘new’
      end
  end
end

I haven’t figured out how to consolidate the validation error messages - If anybody knows how please let me know.

*****************UPDATE August 26, 2006*******************

I created a zip of the code above in a rails app. The DB sql is in a file in the DB folder. You need to create a database called multirecord and then use the sql to set up the tables. This was built using Rails version 1.1.6

You can find the zip file at http://thebitt.com/wp-content/uploads/2006/08/multirecord.zip

Hope it proves helpful.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • bodytext
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Pownce
  • TwitThis

Comments

14 Responses to “Multiple Record Forms for Ruby on Rails”

  1. Ezra Zygmuntowicz on January 4th, 2006 8:39 am

    Hey Alex. Nice post! One thing you can change though is this part:

    @account.valid?
    @user.valid?
    if @account.valid? && @user.valid?

    Its redundant. You only need this part and you can drop the other lines:

    if @account.valid? && @user.valid?

    Cheers-
    -Ezra

  2. Alex on January 4th, 2006 9:14 am

    I thought about that. I can drop the first one @account.valid?, but I need to make sure @user.valid? gets called so I get all the error messages. When @account.valid? fails in the if statement @user.valid? never gets called. Maybe something like

    if @user.valid? uservalid = yes
    if @account.valid? && uservalid == yes

    might work and reduce calls to the model.

  3. Thomas Brinshock on January 26th, 2006 10:14 am

    You’re an absolute legend. I have the Agile Web Development with Rails book but I needed a clear and precise example of how to do this. Precisely the short, sweet little example I needed!! You wouldn’t believe how much this has been frustrating me.

    Thanks again.

    Oh and btw. My ‘tea blog’ account isn’t my main one. Its actually here: blog.straw-dogs.co.uk

  4. dylans on January 27th, 2006 11:02 am

    Did you ever find a way to consolidate the validation errors ?

    BTW… Great post Alex !

  5. Kilka on July 28th, 2006 10:46 am

    Hey Alex,

    Thanks for the post. It’s proven to be very helpful. Unfortunately, I can’t seem to get the following to work:

    @account.users

  6. Alex on August 1st, 2006 5:04 pm

    I’m not sure what the problem is. It’s been a while since I posted this. One thing that occurs to me is to check is to see if all of your models/variables have the plurals /singulars set right.

  7. Don on August 9th, 2006 11:53 pm

    can you fix the spacing in def create?
    also a convoluted way to get both valids to execute is:
    if [@account.valid?, @user.valid?].reject{|i|i}.empty?

  8. Steve on August 11th, 2006 11:12 pm

    This is really useful - its so hard to find an example of this kind of update - and something I’d think just about everyone is going to need to do as soon as you get past the Hello World program. One thing that would really clarify things for me - what are the file names? Is the view new.rhtml?

  9. Alex on August 26th, 2006 5:43 pm

    yes the views file name is new.rhtml and it sits in a folder under views called signup

  10. Nick on October 16th, 2006 5:55 pm

    why don’t you just logically AND the calls to .valid?

    all_valid = @drinker.valid? & @biodata.valid?

    if all_valid
    render …

    note the “&”, which does is a logical AND and evaluates both expressions

  11. Nick on October 16th, 2006 6:14 pm

    here’s a way to consolidate the validation errors:

    errors = @user.errors.full_messages + @account.errors.full_messages

    errors is an array of the full error messages.

  12. alex on October 16th, 2006 7:18 pm

    Nick,

    Thanks. Both those suggestions should work. It would cut out two valid? calls to the DB and the second should give me the error messages I need. I will check out your suggestions and make modes when I get a chance.

    Thanks

    Alex

  13. Jordan Elver on November 13th, 2006 11:35 am

    Nick: Thanks for the “&” tip. I’ve been trying to figure out how to do that for ages.

    Cheers!

  14. Frederico on June 19th, 2007 5:58 am

    Thanks a lot for this awesome post!!!
    Very nice and helpful.

    saved me many hours. ;)

    cheers!

Leave a Reply