Using Devise to create a new Copmany that a User belongs_to in Rails 4

I was creating my first Rails app the other day and although the online tutorials are very useful, I couldn’t find a way to have my devise registration form create a new company and assign it to the new User. After a lot of googling and hair pulling I made it work. I created a rails’ app and put it in Github. The last commit highlighting what I did to make it work. You can see it here Example

It turns out it was very simple so here it is

I will leave setting up rails and generating the Devise views for you to google.
You need to already have a User and Company Model
I will assume you have done all that or you can just clone my example from Github Example

First on our config/routes.rb we add this

 # We are customizing the registration route to add our company fields
devise_for :users, :controllers => { registrations: 'registrations'}

now on our app/controllers/registrations_controller.rb (you will need to create this file)

 class RegistrationsController < Devise::RegistrationsController
  # Because of Rails strong parameter we need to use the Registration controller Override
  # to sanitize inputs
  # Devise automatically knows wich one to use
  private
  def sign_up_params
  params.require(:user).permit( :email, :password,:password_confirmation,
  company_attributes:[:company_name])
  end
  def account_update_params
    # For updates we make sure to let the Company ID pass through or the form will
    # generate a new company every time we edit our details
    params.require(:user).permit(:email,:password, :password_confirmation, :current_password,
    company_attributes: [:id,:company_name])
  end
end

Our User model

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable
  # we set up our User relation ship
  belongs_to :company
  # we tell User that we can take company attributes
  accepts_nested_attributes_for :company
  validates :email, presence: true, uniqueness: {scope: :company_id}
end

Our Company Model

class Company < ActiveRecord::Base
  # Set up Company to have many_users
  has_many :users
  # We want to validate at least one field you can choose any
  # field you want
  validates :company_name, presence: true
  # Add other validations etc...
end

Now for Our Views

the new registration app/views/devise/registrations/new.html.erb


Sign up

<% resource.build_company %> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= devise_error_messages! %>
<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>
<%= f.fields_for :company do |builder| %> <%= builder.label :company_name %>
<%= builder.text_field :company_name %> <%end%>
<%= f.label :password %> <% if @validatable %> (<%= @minimum_password_length %> characters minimum) <% end %>
<%= f.password_field :password, autocomplete: "off" %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
<%= f.submit "Sign up" %>
<% end %> <%= render "devise/shared/links" %>

now our registration edit form

Edit <%= resource_name.to_s.humanize %>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> <%= devise_error_messages! %>
<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>
<%= f.fields_for :company do |builder| %> <%= builder.label :company_name %>
<%= builder.text_field :company_name %> <%end%>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
<% end %>
<%= f.label :password %> (leave blank if you don't want to change it)
<%= f.password_field :password, autocomplete: "off" %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
<%= f.label :current_password %> (we need your current password to confirm your changes)
<%= f.password_field :current_password, autocomplete: "off" %>
<%= f.submit "Update" %>
<% end %>

Cancel my account

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

<%= link_to "Back", :back %>

Finally for testing purposes i am doing this on my welcome page

    <% if user_signed_in? %>
  • <%= link_to "My Account", edit_user_registration_path %>
  • <%= link_to "Log Out", destroy_user_session_path, :method => :delete%>
  • <% else %>
  • <%= link_to "Login", new_user_session_path %>
  • <%= link_to "Sign Up", new_user_registration_path %>
  • <% end %>
Welcome
  1. A coworker stored production assets in Dropbox. Chaos ensued.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.