3 models in 1 template


#1

hello,

I’d like to get user data in one template.

The relations are:
user has_one user_adress
user has_one user_account

The following template doesn’t save any (valid) data. I think the
submit button doesn’t work.
All 3 models should be validated when save is called.

<%= error_messages_for ‘user’ %>
<%= error_messages_for ‘user_adress’ %>
<%= error_messages_for ‘user_account’ %>

Please enter your data:
<% form_for :user do |form| %>
    <label for="user_first_name">firstname:</label>
    <%= form.text_field :first_name, :size => 40 %>
  </p>
  <p>
    <label for="user_surname">surname:</label>
    <%= form.text_field :surname, :size => 40 %>
  </p>
  <p>
    <label for="user_birthdate">date of birth</label><br/>
    <%= date_select 'user', 'birthdate', :include_blank => true,
    :order => [:day, :month, :year], :start_year => 1900, :default

=> :blank %>



email:
<%= form.text_field :email, :size => 40 %>



username:
<%= form.text_field :username, :size => 40 %>



password:
<%= form.password_field :password, :size => 40 %>



passwort
confirmation:
<%= form.password_field :password_confirmation, :size => 40 %>


<% end %>
<legend>Your adress:</legend>
<% form_for :user_adress do |form| %>
  <p>
    <label for="user_adress_street">street:</label>
    <%= form.text_field :street, :size => 40 %>
  </p>
  <p>
    <label for="user_adress_nr">number:</label>
    <%= form.text_field :nr, :size => 40 %>
  </p>
  <p>
    <label for="user_adress_postcode">postcode:</label>
    <%= form.text_field :postcode, :size => 40 %>
  </p>
  <p>
    <label for="user_adress_city">City:</label>
    <%= form.text_field :city, :size => 40 %>
  </p>
<% end %>

<legend>Your payment details:</legend>
<% form_for :user_account do |form| %>
  <p>
    <label for="user_account_bank">credit institution:</label>
    <%= form.text_field :bank, :size => 40 %>
  </p>
  <p>
    <label for="user_account_bank_code">bank code:</label>
    <%= form.text_field :bank_code, :size => 40 %>
  </p>
  <p>
    <label for="user_account_account_number">account number:</

label>
<%= form.text_field :account_number, :size => 40 %>


<% end %>

<%= submit_tag “Register”, :class => “submit” %>


#2

This creates 3 forms, but no submit tag in any of them.

Try using this:

form_for :user, @user, :url => {:action => :new} do |form|
#…your fields for user

fields_for :user_address, @user_address do |fields|
#…your fields for user_adress in the following form:
# fields.textarea (arguments)
end

fields_for :user_account, @user_account do |fields|
#same as for user_adress
end

<%= submit_tag “Register”, :class => “submit” %>
end

:user is the class of the object of interest
@user is an actual instance (which could have another name like
@new_user)
:url points the form to it’s target

same for the fields_for, but subforms do not get a target.

Have Fun
Skade


#3

there’s also a problem in my controller. Neither does it save anything
to the database nor validate the models.

The template is register.rhtml. I wrote it as you said.

def register
@user = User.new
end

def new
if @user.save
@user.adress = @user_adress
@user.account = @user_account
flash[:notice] = ‘Registration was successful.’
redirect_to :action => ‘index’
else
render :action => ‘register’
end
end


#4

I forgot to say that the relations are dependent.

And not everyone does have an account. So, if there’s nothing in the
account field, the account shouldn’t be saved.


#5

Martin Luy wrote:

there’s also a problem in my controller. Neither does it save anything
to the database nor validate the models.

The template is register.rhtml. I wrote it as you said.

def register
@user = User.new
end

def new
if @user.save
@user.adress = @user_adress
@user.account = @user_account
flash[:notice] = ‘Registration was successful.’
redirect_to :action => ‘index’
else
render :action => ‘register’
end
end

Please consider that all Rails operations are stateless. You need to
instantiate a new User in def new. You will find the contents of the
form via params(:user).

Try:

def new
@user = User.new(params(:user))
@user.address.build(params(:user_adress))
@user.account.build(params(:user_account))
if @user.save!
flash[:notice] = ‘Registration was successful.’
redirect_to :action => ‘index’
else
render :action => ‘register’
end
end

I hope, you get the point, i can’t check the code right now.


#6

Martin Luy wrote:

I forgot to say that the relations are dependent.

And not everyone does have an account. So, if there’s nothing in the
account field, the account shouldn’t be saved.

class User < ActiveRecord::Base
validates_associated :account, :address
end


#7

Thanks for your help, I got to the following working code. 2 more
questions after the code.

In the controller:

def register
@user = User.new(params[:user])
@user.time_of_registration = Time.now
@user.user_adress = UserAdress.new(params[:user_adress])
@user.user_account = UserAccount.new(params[:user_account])
if request.post? and @user.save
flash[:notice] = ‘Registration was successful.’
redirect_to :action => ‘login’
end
end

register.rhtml:

<%= error_messages_for ‘user’ %>

Please enter your data:
<% form_for :user, @user do |form| %>
  <p>
    <label for="user_first_name">First name:</label>
    <%= form.text_field :first_name, :size => 40 %>
  </p>
  ...

  <% fields_for :user_adress, @user_adress do |fields| %>
    ...
  <% end %>

  <p>If you want to pay using debit, please enter your bank

account:


<% fields_for :user_account, @user_account do |fields| %>


credit institution:
<%= fields.text_field :bank, :size => 40 %>



bank code:
<%= fields.text_field :bank_code, :size => 40 %>



account number:</
label>
<%= fields.text_field :account_number, :size => 40 %>


<% end %>
  <%= submit_tag "Register", :class => "submit" %>

<% end %>

The user model:

class User < ActiveRecord::Base

has_one :user_adress, :dependent => true
has_one :user_account, :dependent => true

validates_associated :user_account, :user_adress

end

The account model:

class UserAccount < ActiveRecord::Base
belongs_to :user

validates_presence_of :bank, :bank_code, :account_number

validates_numericality_of …
validates_inclusion_of …
validates_format_of …
end

Questions:

Validation of user_account and user_adress looks like “User adress is
invalid”. I would like to show the errors for the children classes
explicitly.

How can I change “validate_presence_of” in UserAccount so that either
all or no fields are entered?

Thanks,
Luma