Associated models and a nested form with validation not working - ruby-on-rails

Update2: I've cleaned up the code, which seems to have solved some of the problems. I've posted the new code as a new question here.
Update: Organization and User have a 1:many relationship. My question concerns a joined signup form where both an organization and user are required. After maxcal's help on the original post, I've written a new create method for my nested form ("organization has many users"), as shown below. Also I added begin...rescue...end to the create method. The situation/problem now:
Submitted with all valid info it works correctly.
Submitted with invalid info for organization (doesn't matter if user is also invalid or not), it renders the page with the error messages, as we want it to, but it only shows errors for the organization details. Also, for the user details it has then emptied all the fields, which it shouldn't.
Submitted with invalid info only for user, it renders the form again but without any error messages and all fields for user have been emptied.
Anyone got an idea what is wrong with the code? The problem seems to be more with the nested user than with organization (the parent). Also, users_attributes.empty? doesn't work, since an empty submitted form still includes such attributes, according to the log:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"***", "organization"=>{"name"=>"", "bag"=>"", "users_attributes"=>{"0"=>{"email"=>"", "username"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "usertype"=>"2", "admin"=>"true"}}}, "commit"=>"Register"}
.
def create
#organization = Organization.new(new_params.except(:users_attributes))
begin
if users_attributes.empty?
#organisation.errors.add(:users, 'No user provided')
end
#organization.transaction do
#organization.save!
if users_attributes.any?
#organization.users.create!(users_attributes)
end
end
rescue ActiveRecord::RecordInvalid => invalid
if #organization.persisted?
if #organization.users.any?
#organization.users.each do |single_user|
single_user.send_activation_email
end
end
flash[:success] = "Confirmation email sent."
redirect_to root_url
else
#organization.users.build if #organization.users.blank?
render :new
end
end
end
private
# converts the hash of nested attributes hashes to an array
def users_attributes
new_params[:users_attributes].values
end
end
Original question:
I have two associated models and a nested form with validation. Unfortunately, it’s not working. 1) On seeding it generates the error Validation failed: Users organization can't be blank. I previously posted a question about this and prematurely concluded it had solved it. It hasn’t. 2) Submitting my nested signup form with all fields filled in correctly, produces the flash error message The form contains 1 error. Users organization can't be blank.
How should I adjust my code to solve these issues?
Model files:
#User model
belongs_to :organization, inverse_of: :users
validates_presence_of :organization_id, :unless => 'usertype == 1'
# Organization model
has_many :users, dependent: :destroy
accepts_nested_attributes_for :users, :reject_if => :all_blank, :allow_destroy => true
validate :check_user
private
def check_user
if users.empty?
errors.add(:base, 'User not present')
end
end
Organization Controller methods
def new
#organization = Organization.new
#user = #organization.users.build
end
def create
#organization = Organization.new(new_params)
if #organization.save
#organization.users.each do |single_user|
single_user.send_activation_email # Method in user model file.
end
flash[:success] = "Confirmation email sent."
redirect_to root_url
else
#organization.users.build if #organization.users.blank?
render 'new'
end
end
def new_params
params.require(:organization).permit(:name, :bag,
users_attributes: [:email, :username, :usertype, :password, :password_confirmation])
end
The form:
<%= form_for #organization, url: organizations_path do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_field :name %>
<%= f.text_field :bag %>
<%= f.fields_for :users do |p| %>
<%= p.email_field :email %>
<%= p.text_field :username %>
<%= p.text_field :fullname %>
<%= p.password_field :password %>
<%= p.password_field :password_confirmation %>
<%= p.hidden_field :usertype, value: 2 %>
<% end %>
In my Seeds file I have:
Organization.create!(name: "Fictious business",
address: Faker::Address.street_address,
city: Faker::Address.city,
users_attributes: [email: "helpst#example.com",
username: "helpyzghtst",
usertype: 2,
password: "foobar",
password_confirmation: "foobar"])
The log on the error on submitting the signup form:
Started POST "/organizations"
Processing by OrganizationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0cR***Nnx4iReMiePg==", "organization"=>{"name"=>"test21", "bag"=>"tes21", "users_attributes"=>{"0"=>{"email"=>"test21#example.com", "username"=>"test21", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "usertype"=>"2"}}}, "commit"=>"Register"}
(0.2ms) BEGIN
User Exists (1.1ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('test21#example.com') LIMIT 1
(0.7ms) SELECT "users"."email" FROM "users" ORDER BY "users"."username" ASC
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE LOWER(users"."username") = LOWER('test21') LIMIT 1
Organization Exists (0.6ms) SELECT 1 AS one FROM "organizations" WHERE LOWER("organizations"."name") = LOWER('test21') LIMIT 1
Organization Exists (0.4ms) SELECT 1 AS one FROM "organizations" WHERE LOWER("organizations"."bag") = LOWER('tes21') LIMIT 1
(0.2ms) ROLLBACK

Your validation does not work due to a Catch-22
To apply for this job, you would have to be insane; but if you are
insane, you are unacceptable.
ActiveRecord models get their ID from the database when they are saved.
But the validation on the nested user runs before the organization is inserted into the the database.
You would guess that just checking validates_presence_of instead would pass:
validates_presence_of :organization, unless: -> { usertype == 1 }
Unfortunatly not. In order for validates_presence_of :organization to pass the organization must be persisted to the database. Catch-22 again.
In order for the validation to pass we would need to split creating the organization and user into two steps:
org = Organization.create(name: 'M & M Enterprises')
user = org.users.build(username: 'milo_minderbinder', ...)
user.valid?
Unfortunatly the means that you cannot use accepts_nested_attributes_for :users - well at least not straight off the bat.
By using a transaction we can insert the organization into the the database and and roll back if the user is not valid.
def create
#organization = Organization.new(new_params.except(:users_attributes))
#organization.transaction do
#organization.save!
if new_params[:users_attributes].any?
#organization.users.create!(new_params[:users_attributes])
end
end
if #organization.persisted?
# ...
if #organization.users.any?
# send emails ...
end
else
#organization.users.build if #organization.users.blank?
render :new
end
end
Followup questions
We use #organization.persisted? since we presumably want to redirect to the newly created organisation no matter if the there is a User record created.
because the emails are sent to users? It shouldn't matter since organization is rolled back if no user is created.
The transaction is not rolled back if there is no user created. Only if the user(s) fails to save due to invalid parameters. This is based on your requirement:
But an organization can also (temporarily) have no users.
If you need the #organisation to be invalid without users you could do:
#organisation.errors.add(:users, 'No users provided') unless new_params[:users_attributes].any?
#organization.transaction do
#organization.save!
if new_params[:users_attributes].any?
#organization.users.create!(new_params[:users_attributes])
end
end
You would use #organization.users.any? to check if there are any users. #organization.users.persisted? will not work since .persisted? is a method on model instances - not collections.
On a different note, I assume it's not possible to overwrite/update an existing organization/user with this method (which shouldn't be) instead of always creating a new record?
Right, since this will always issue two SQL insert statements it will not alter existing records.
It is up to you however to create validations that guarantee the uniqueness of the database columns (IE you don't want several records with the same user.email or organiation.name).
On the plus side is that none of these caveats apply when updating an existing organization:
def update
#organisation.update(... params for org and and users ...)
end
Since you don't get the whole chicken or egg dilemma when validating the users.

Related

How to save a nested resource in ActiveRecord using a single form (Ruby on Rails 5)

I have two entities with a many-to-one relationship. User has many Addresses. When creating a User I want the form to also create a single Address. The entities are nested.
Approach 1:
The code below works, but only saves the User, no associated Address.
Reading around, I thought that the accepts_nested_attributes_for would automatically save the address. I'm not sure, but it may be that this isn't working because the parameters I'm getting into the Controller don't actually appear to be nested, ie. they look like:
"user"=>{"name"=>"test"}, "address"=>{"address"=>"test"}
Rather than being nested like this:
"user"=>{"name"=>"test", "address"=>{"address"=>"test"} }
I assume this could be due to something wrong in my form, but I don't know what the problem is...
Approach 2:
I have also tried changing the controller - implementing a second private method, address_params, which looked like params.require(:address).permit(:address), and then explicitly creating the address with #user.address.build(address_params) in the create method.
When tracing through this approach with a debugger the Address entity did indeed get created successfully, however the respond_to do raised an ArgumentError for reasons I don't understand ("respond_to takes either types or a block, never both"), and this rolls everything back before hitting the save method...
[EDIT] - The respond_to do raising an error was a red herring - I was misinterpreting the debugger. However, the transaction is rolled back for reasons I don't understand.
Questions:
Is one or the other approach more standard for Rails? (or maybe neither are and I'm fundamentally misunderstanding something)
What am I doing wrong in either / both of these approaches, and how to fix them so both User and Address are saved?
Relevant code below (which implements Approach 1 above, and generates the non-nested params as noted):
user.rb
class User < ApplicationRecord
has_many :address
accepts_nested_attributes_for :address
end
address.rb
class Address < ApplicationRecord
belongs_to :user
end
users_controller.rb
class UsersController < ApplicationController
# GET /users/new
def new
#user = User.new
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user}
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
def user_params
params.require(:user).permit(:name, address_attributes: [:address])
end
end
_form.html.erb
<%= form_for(user) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= fields_for(user.address.build) do |u| %>
<div class="field">
<%= u.label :address %>
<%= u.text_field :address %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
UPDATE 1:
After making the changes suggested by #Ren, I can see that the parameters look more like what I would've expected for nested resources:
"user"=>{"name"=>"test", "addresses_attributes"=>{"0"=>{"address"=>"test"}}}
However, when trying to save the user, the transaction is still rolled back for reasons I don't understand. The output I get from the users.new page is:
2 error prohibited this user from being saved:
Addresses user must exist
Addresses user can't be blank
However, using byebug, after the #user = User.new(user_params) call, things look as I would expect them:
(byebug) #user
#<User id: nil, name: "test", created_at: nil, updated_at: nil>
(byebug) #user.addresses
#<ActiveRecord::Associations::CollectionProxy [#<Address id: nil, user_id: nil, address: "test", created_at: nil, updated_at: nil>]>
Obviously the user.id field is not set until the record is written to the DB, so equally the address.user_id field cannot be set until user is saved, so maybe this is caused by some sort of incorrect ordering when ActiveRecord is saving to the database? I will continue to try to understand what's going on by debugging with byebug...
UPDATE 2:
Using rails console to test, saving User first and then adding the Address works (both records get written to the DB, although obviously in 2 separate transactions):
> user = User.new(name: "consoleTest")
> user.save
> user.addresses.build(address: "consoleTest")
> user.save
Saving only once at the end results in the same issues I'm seeing when running my program, ie. the transaction is rolled back for some reason:
> user = User.new(name: "consoleTest")
> user.addresses.build(address: "consoleTest")
> user.save
As far as I can tell from debugging with rails console, the only difference between the state of user.addresses in these two approaches is that in the first address.user_id is already set, since the user.id is already known, while as in the second, it is not. So this may be the problem, but from what I understand, the save method should ensure entities are saved in the correct order such that this is not a problem. Ideally it would be nice to be able to see which entities save is trying to write to the DB and in which order, but debugging this with byebug takes me down an ActiveRecord rabbit-hold I don't understand at all!
UPDATE: As opposed to previous versions, Rails 5 now makes it required that in a parent-child belongs_to relationship, the associated id of the parent must be present by default upon saving the child. Otherwise, there will be a validation error. And apparently it isn't allowing you to save the parent and child all in one step... So for the below solution to work, a fix would be to add optional: true to the belongs_to association in the Address model:
class Address < ApplicationRecord
belongs_to :user, optional: true
end
See my answer in a question that branched off from this one:
https://stackoverflow.com/a/39688720/5531936
It seems to me that you are mixing up the singular and plural of your address object in such a way that is not in accordance with Rails. If a User has many addresses, then your Model should show has_many :addresses and accepts_nested_attributes_for should have addresses:
class User < ApplicationRecord
has_many :addresses
accepts_nested_attributes_for :addresses
end
and your strong params in your controller should have addresses_attributes:
def user_params
params.require(:user).permit(:name, addresses_attributes: [:id, :address])
end
Now if you want the User to just save One Address, then in your form you should have available just one instance of a nested address:
def new
#user = User.new
#user.addresses.build
end
By the way it seems like your form has fields_for when it should be f.fields_for:
<%= f.fields_for :addresses do |u| %>
<div class="field">
<%= u.label :address %>
<%= u.text_field :address %>
</div>
<% end %>
I highly recommend that you take a look at the Rails guide documentation on Nested Forms, section 9.2. It has a similar example where a Person has_many Addresses. To quote that source:
When an association accepts nested attributes fields_for renders its
block once for every element of the association. In particular, if a
person has no addresses it renders nothing. A common pattern is for
the controller to build one or more empty children so that at least
one set of fields is shown to the user. The example below would result
in 2 sets of address fields being rendered on the new person form.
def new
#person = Person.new
2.times { #person.addresses.build}
end

rails autocomplete how to use exising record

I'm new to rails , and I have a problem with the nested forms and all of that.
I have a User model, and an Organization model.
When I want to create a user, I want to specify from which organization does he comes from.
Either the organization name is already in the database or if it's not, I want to create a new record and associate that record the User model.
I have hard time understanding all the relations (many-to-many etc) implications in the rails framework, but so far I've got this.
model/organization.rb
class Organization < ActiveRecord::Base
has_many :user
validates_presence_of :name
end
model/user.rb (short)
class User < ActiveRecord::Base
belongs_to :organization
accepts_nested_attributes_for :organization
#####
end
From this, in the console, I can create user and specify and organization name , and it will create a new record for the user and a new record for the organization.
The problem is that it creates a new organization each time.
I want to be able to associate an already existing organization to a new user.
I can get the list of organization with things like typeahead.js for the form, so the name will be the same when the user selects one. But I don't know how to relate the two (the newly created user and already existing organization).
I thought of putting a hidden field with the id of the organization, and check in the controller if this id exists. If it does, put this id, if it doesn't create a new one. But I don't even know how to do this. In the console, when I update the attributes of a user, for example , with an organization_id = 3 which exists :
u.update_attributes( :organization_attributes => { id: 3 } )
It rejects saying he didn't find a user with ID=... with Organization.id = 3 ...
I don't understand.
I suppose since this is a common case, that this should be easy , but it's messing with my head.
If someone is willing to explain to me, I'd be very grateful.
Thank you.
EDIT
i've just tried something in my controller but that doesn't work either.
def create
#user = User.new(user_params) # :user object built from user inputform
org = Organization.find_by(name:user_params[:organization_attributes][:name])
if org
#user.organization.id = org.id
end
if #user.save
# signin the user (token etc)
sign_in #user
flash[:success] = "Registration sucessfull !"
redirect_to #user
else
render 'new'
end
end
+user_controller (strong params)
def user_params
params.require(:user).permit(:lname,:email,:fname,:password,:password_confirmation,
:gender,:role,:display_private,:link_li,:country,:city,:phone,:hobbies,
:avatar,:org_name, :organization_attributes => [ :id, :name])
end
+form.html.erb
<%= u.fields_for :organization do |o| %>
<%= o.label "Organization" %>
<!-- PUT ORGA -->
<%= o.text_field :name, class:"form-control" %>
<% end %>
I would write a custom method for this:
#in User
def organization_name
(org = self.organization) && org.name
end
def organization_name=(name)
if org = Organization.find_by_name(name)
self.organization = org
else
self.organization = Organization.create(:name => name)
end
end
Now, because you've got a getter and setter method (ie two methods with the same name, apart from the = sign), you can treat organization_name like an attribute of User and put it in a form field like
f.input :organization_name
The input will get the current value from #user.organization_name and will call #user.organization_name= with the new value.
First take away the accepts_nested_attributes from the model.
Then in your controller you should do something like:
def create
#user = User.new(user_params) # :user object built from user inputform
org = Organization.where(name: user_params[:organization_attributes][:name]).first || Organization.create(name: user_params[:organization_attributes][:name])
#user.organization = org
if #user.save
# signin the user (token etc)
sign_in #user
flash[:success] = "Registration sucessfull !"
redirect_to #user
else
render 'new'
end
end
In your app/model/user.rb
def self.create(name, attribute1, ... ,organization)
user = User.new(:name => name, :atr_1 => attribute_1, ....:atr_n => attribute_n)
user.organization = organization
raise "user not created" if !user.save
user
end
In users_controller.rb
def create
org = Organization.find params['organization'] #expecting the param to be Organization#id
user = User.create(params['name'], ..., org)
render :json => {:message => "user created"}
end

Ruby on Rails, find if a certain value exists in a column

I'm building a website with user authentication. And I just noticed that if I create a user with an existing email, it just doesn't work which is normal, but I'd like to give feedback to the user. So for that I need to determine if any user has already that email.
I've tried some things like:
if User.email.include? params[:user][:email]
flash.now[:error] = "A user with this password already exists"
render :action => :new, :layout => 'signin-layout.html.erb'
Those are the columns for User:
2.1.0 :014 > User.column_names
=> ["id", "name", "email", "created_at", "updated_at", "password_digest", "remember_token", "admin", "team_id", "teamLeader"]
And the result I get is a big fat error:
undefined method `email' for #<Class:0x00000102b9a908>
So if anybody sees what I'm doing wrong, or knows another way to do it, that would be great.
Cheers
Try this:
if User.exists?(:email => params[:user][:email])
flash.now[:error] = "A user with this password already exists"
render :action => :new, :layout => 'signin-layout.html.erb'
...
else
# more code here..
end
Also, you can add validations when you're creating the object:
class User
validates_uniqueness_of :email
More on different validations here: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
I believe this way of doing the validation is wrong, you should validate the uniqueness of the email in the User model itself like below
validates :email, uniqueness: true #User model
This way the validation would be on the the User model. The problem with the condition you are using is that it is accessing an instance method specific to objects as a class method. So User.email means that there is a method called email that has the same logic for all the instances of the user class or more formally a class method which you don't have here. The email is an attribute specific to each user an instance attribute/variable (Each user has a different email).
You can see/show the validation errors present on the model using #user.errors.full_messages where #user is the instance you are trying to register/save.
This is how I would normally do it if this action is for registering users i.e. creating new users.
class User < ActiveRecord::Base
#attribute accessors and accessible
validates :email, uniqueness: true
end
class UsersController < ApplicationController
def create
#user = User.new params[:user]
if #user.save
#code for redirect or rendering the page you want
else
render 'new'
end
end
end
#new.html.erb
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div>
<ul>
<% #job.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
#form fields
<% end %>
This way you display all the error messages to the user at the top of the registration form.

Solution to "Can't mass-assign protected attributes" by adding the foreign key to attr_accessible

I need to create a CRUD that allow create and update projects and one of the attributes is the client that owns the project. When the project is created or edited, the client is selected using a select tag.
I have this model:
class Cliente < ActiveRecord::Base
attr_accessible :nombre
has_many :proyectos
end
class Proyecto < ActiveRecord::Base
attr_accessible :nombre, :cliente_id
belongs_to :cliente
end
this controller:
class ProyectosController < ApplicationController
def new
#proyecto = Proyecto.new
#clientes = Cliente.order(:nombre)
end
def edit
#proyecto = Proyecto.find(params[:id])
#clientes = Cliente.order(:nombre)
end
def create
#proyecto = Proyecto.new(params[:proyecto])
if #proyecto.save
redirect_to #proyecto, notice: 'Proyecto was successfully created.'
else
render action: "new"
end
end
end
def update
#proyecto = Proyecto.find(params[:id])
if #proyecto.update_attributes(params[:proyecto])
redirect_to #proyecto, notice: 'Proyecto was successfully updated.'
else
render action: "edit"
end
end
end
and this form on the view (in haml):
= form_for #proyecto do |f|
= f.label :cliente
= f.collection_select :cliente_id, #clientes, :id, :nombre
= f.label :nombre
= f.text_field :nombre
= f.submit 'Save'
The code was generated with scaffold, I just removed the unnecesary parts and added the code to create the select.
Initially, on the model Proyecto I had this:
attr_accessible :nombre
but get the error "Can't mass-assign protected attributes: cliente_id". Searching here on stackoverflow for similar problems, I found that I must add cliente_id to attr_accessible, but searching on google also found that I must not add foreing keys to attr_accessible due to security issues, which is contradictory.
Is this the correct way to code my create and update methods, adding cliente_id to attr_accessible? If not, what is the correct way?
I'm working with rails 3.2.8 and ruby 1.9.3p194
In this case you must have the client_id as attr_accessible. The reason is because you are allowing the user to set the client through the select box on the form.
However, this poses a security concern. Imagine that you are only showing a specific user 3 different clients he can pick from (IDs: 1, 2, 3). If the user modifies the form manually, he can assign a client with ID #4 to his project which can be a security issue or just a bug.
To close the security issue, add a validation to your Project model that makes sure that the client ID is valid.

Passing params to a new template on a failed create action when using accepts_nested_attributes_for

I may just be missing something simple, but I am relatively inexperienced so it is likely. I've searched extensively for a solution without success.
I am using the fields_for function to build a nested form using the accepts_nested_attributes_for function. If the submit on the form fails the params are passed to the render of the new template only for the parent model. How do I pass the nested params for the child model so that fields that have been filled out previously remain filled. Note that I am using simple_form and HAML but I assume this shouldn't impact the solution greatly.
My models:
class Account < ActiveRecord::Base
attr_accessible :name
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users, :reject_if => proc { |a| a[:email].blank? }, :allow_destroy => true
end
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation
belongs_to :account
end
My accounts controller:
def new
#account = Account.new
#account.users.build
end
def create
#account = Account.new(params[:account])
if #account.save
flash[:success] = "Welcome."
redirect_to #account
else
#account.users.build
<- I suspect I need something here but unsure what
render :new
end
end
The key part of the accounts/new view:
= simple_form_for #account do |f|
= f.input :name
= f.simple_fields_for :users do |u|
= u.input :email
= u.input :password
= u.input :password_confirmation
= f.button :submit, :value => "Sign up"
My params on a failed save are:
:account {"name"=>"In", "users_attributes"=>{"0"=>{"email"=>"u#e.com", "password"=>"pass", "password_confirmation"=>"pass"}}}
As you can see, the key information, in the users_attributes section, is stored but I can't seem to have the email address default into the new form. Account name on the other hand is filled automatically as per Rails standard. I'm not sure if the solution should live in the accounts controller or in the accounts/new view, and have not had any luck with either.
Answers with .erb are, of course, fine.
I'm fairly new to Ruby and Rails so any assistance would be much appreciated.
The problem lies with attr_accessible, which designates the only attributes allowed for mass assignment.
I feel a bit silly in that I actually stated the problem in a comment last night and failed to notice:
accepts_nested_attributes_for :users will add a users_attributes= writer to the account to update the account's users.
This is true, but with attr_accessible :name, you've precluded every attribute but name being mass-assigned, users_attributes= included. So when you build a new account via Account.new(params[:account]), the users_attributes passed along in params are thrown away.
If you check the log you might note this warning:
WARNING: Can't mass-assign protected attributes: users_attributes
You can solve your original problem by adding :users_attributes to the attr_accessible call in the account class, allowing it to be mass-assigned.
Amazingly, after reading a blog post this evening, and some more trial and error, I worked this out myself.
You need to assign an #user variable in the 'new' action so that the user params are available for use in the 'create' action. You then need to use both the #account and #user variables in the view.
The changes look like this.
Accounts Controller:
def new
#account = Account.new
#user = #account.users.build
end
def create
#account = Account.new(params[:account])
#user = #account.users.build(params[:account][:user]
if #account.save
flash[:success] = "Welcome."
redirect_to #account
else
render :new
end
end
The accounts/new view changes to:
= simple_form_for #account do |f|
= f.input :name
= f.simple_fields_for [#account, #user] do |u|
= u.input :email
= u.input :password
= u.input :password_confirmation
= f.button :submit, :value => "Sign up"
In this case the params remain nested but have the user component explicitly defined:
:account {"name"=>"In", "user"=>{"email"=>"user#example.com", "password"=>"pass", "password_confirmation"=>"pass"}}
It has the additional side effect of removing the #account.users.build from within the else path as #numbers1311407 suggested
I am not certain whether their are other implications of this solution, I will need to work through it in the next few days, but for now I get the information I want defaulted into the view in the case of a failed create action.
#Beerlington and #numbers1311407 I appreciate the help in guiding me to the solution.

Resources