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


<h2>Sign up</h2>
<!-- We need to build a company first so we can use it in our form builder -->
<% resource.build_company %>


<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>
  <!--  We add this to the Registration form so we can create a new company 
	You can add more company fields here
 -->
 <div class="field">
   <%= f.fields_for :company do |builder| %>
    <%= builder.label :company_name %><br />
    <%= builder.text_field :company_name %>
	<%end%>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @validatable %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

now our registration edit form

<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>
<!--  We add this to the Registration Edit form so we can Update company information 
	You can add more company fields here
 -->
 <div class="field">
   <%= f.fields_for :company do |builder| %>
    <%= builder.label :company_name %><br />
    <%= builder.text_field :company_name %>
	<%end%>
  </div>
  
  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

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

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

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

<ul>
<!-- for neatness you get login and sign up links on non registered users
Otherwise you get my account link and logout -->

<% if user_signed_in? %>
  <li><%= link_to "My Account", edit_user_registration_path %></li>
  <li><%= link_to "Log Out", destroy_user_session_path, :method => :delete%></li>
<% else %>
<li><%= link_to "Login",  new_user_session_path %></li>
<li><%= link_to "Sign Up",  new_user_registration_path %></li>
<% end %>
</ul>
Welcome

4 Comments


  1. Thank you so much , it helps me a lot. just a little typo in this line
    “now on our app/controllers/regristrations_controller.rb (you will need to create this file)” that supposed to be registrations_controller.rb

    I also find out a simple way to do it, without override the registrations_controller. I just add this line in my application_controller

    before_action :configure_permitted_parameters, if: :devise_controller?

    protected
    def configure_permitted_parameters

    devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password, :password_confirmation, {company_attributes:[:company_name]} ])
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :password, :password_confirmation, {company_attributes:[:company_name, :id]}])
    end

    and i follow what carlos did, and it also works 🙂

    Reply

  2. Hello, I don’t know why I’m always getting an error here:

    anyone knows why?

    Reply

    1. can you show me where again? surround your code in < pre >< / pre > tags

      Reply

Leave a Reply

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