Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Rails 4 Devise user sign up with Company name in single nested form

I have a Rails 4 app with a simple default Devise registration flow with a User model. Now I've added a Company model with a one-to-many relationship between a Company and User model (A company has_many users and a user belongs_to a company).

I want the user to select a company name while signing up, so the sign up form has 3 fields: Company name, user email and password.

I get a "Unpermitted parameters: company" error even though I think I'm handling the strong params issue.

I have read all the SO answers to similar questions but none of the answers work. The relevant snippets of my code are below:

#routes.rb
devise_for :users, :controllers => { :invitations => 'users/invitations', 
                                      :registrations => 'users/registrations',
                                      :omniauth_callbacks => "users/omniauth_callbacks"
                                    }

resources :companies


#MODELS
#user.rb
class User < ActiveRecord::Base
  devise :invitable, :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable
  devise :omniauthable, :omniauth_providers => [:google_oauth2, :mailchimp, :stripe_connect, :xero]

  belongs_to :company
  accepts_nested_attributes_for :company
end

#company.rb
class Company < ActiveRecord::Base
  has_many :users
end



#CONTROLLER
#users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController 
  before_filter :configure_permitted_parameters

  def new
    build_resource({})
    self.resource.company = Company.new
    respond_with self.resource
  end

  def create
    super
  end

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) do |u|
      u.permit(:email, :password, :password_confirmation, company_attributes: [:name])
    end
  end
end


#application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

  def after_sign_in_path_for(resource)
    #some_path
  end
end



#VIEW
#sign up form
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  .form-group
    = f.email_field :email, placeholder: "Email", class: "form-control"
    = hidden_field_tag "plan", params[:plan]
  .form-group
    = f.password_field :password, placeholder: "Password", class: "form-control"
  .form-group
    = f.fields_for resource.company do |cf|
      = cf.text_field :name, placeholder: "Name of your company", class: "form-control" 
  .submit= submit_tag "Sign up now", :class => "button"

The params hash passed to Users::RegistrationsController is as follows:

{"utf8"=>"✓", "authenticity_token"=>"uWMrX3qVTLL2A1g1ONtBxuj72/GMRZqG5rcOvba/8p4=", "user"=>{"email"=>"[email protected]", "password"=>"password", "company"=>{"name"=>"F corp"}}, "plan"=>"x", "commit"=>"Sign up now"}
like image 490
Web Dev123 Avatar asked Nov 10 '22 00:11

Web Dev123


1 Answers

It looks like your params sanitizer isn't quite right. Try this:

def configure_permitted_parameters
  devise_parameter_sanitizer.for(:sign_up) do |u|
    u.permit(:email, :password, :password_confirmation, company: [:name])
  end
end

See the Nested Parameters section in the Strong Parameters docs for more details.

like image 85
Pete Keen Avatar answered Nov 14 '22 23:11

Pete Keen