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

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 *

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