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
- Accounts has two fields
- id
- name
- Users has four fields
- id
- first_name
- last_name
- account_id
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.
Comments
14 Responses to “Multiple Record Forms for Ruby on Rails”
Leave a Reply








My name is Alex Nesbitt. This is my blog. I publish Digital Podcast where I evangelize new media and marketing innovation, with a focus on digital media, social media, social networks, social analytics and influencer marketing.
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
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.
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
Did you ever find a way to consolidate the validation errors ?
BTW… Great post Alex !
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
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.
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?
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?
yes the views file name is new.rhtml and it sits in a folder under views called signup
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
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.
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
Nick: Thanks for the “&” tip. I’ve been trying to figure out how to do that for ages.
Cheers!
Thanks a lot for this awesome post!!!
Very nice and helpful.
saved me many hours.
cheers!