Devise strong_params on Nested attributes form

37 Views Asked by At

I am following this tutorial [https://kakimotonline.com/2014/03/30/extending-devise-registrations-controller/][1], whose purpose is creating a Devise User, and its owning Company on the same form.

Models :

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable

  belongs_to :company, optional: true
  accepts_nested_attributes_for :company

end
user model has a reerence to company :
add_reference(:users, :company, {:foreign_key=>true})

I was surprised to see that the 'belonged' can have the accepts_nested mention (thought only the owner could)

class Company < ActiveRecord::Base
 
  has_one :user
 
end

The form view is :

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <div class="controls">
    <%= f.fields_for :company do |company_form| %>
      <%= company_form.text_field :cnpj  %>
    <% end %>
  </div>
  <div class="controls">
    <%= f.text_field :email %>
  </div>
  <div class="controls">
    <%= f.password_field :password %>
  </div>
  <div class="controls">
    <%= f.password_field :password_confirmation %>
  </div>
  <%= f.submit "Submit" %>
<% end %>

The registration controller is created to substitute the default one :

**controllers/registrations_controller.rb**
class RegistrationsController < Devise::RegistrationsController
 
  def new
    build_resource({})
    self.resource.company = Company.new
    respond_with self.resource
  end
  
  def create
    @user = User.new sign_up_params
    @user.save
  end
end

strong_prams permission :

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

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

with this route

MyApp::Application.routes.draw do
 
  devise_for :users, controllers: { registrations: "registrations" }
 
end

On the console, I can create instances :

User.create(email:'[email protected]',
            password:'password',
            password_confirmation:'password',
            company_attributes: { name: 'nours' })

creates one user, and his associated company :)

But the form fails in the #create : . The route works, the params are OK, #create retrieves the right permitted values,

=>{"email"=>"[email protected]", "password"=>"zigzig", "password_confirmation"=>"zigzig", "company_attributes"=>{"name"=>"tata toto"}}```
but creation of instance 
```>> User.new(sign_up_params) 
=> #<User id: nil, email: "", created_at: nil, updated_at: nil, company_id: nil>```, 
the same with 
```>> build_resource sign_up_params  
=> #<User id: nil, email: "", created_at: nil, updated_at: nil, company_id: nil>```

What's wrong with strong_params ?


  [1]: https://kakimotonline.com/2014/03/30/extending-devise-registrations-controller/
1

There are 1 best solutions below

2
On

The reason you’re getting this error is because you have belongs_to :company in your user model. This means there has to be a company or the user won’t save. Try changing it to belongs_to :company, optional: true.

Starting with Rails 5.0, “all model’s belongs_to associations are now treated as if the required: true option is present”. You can find out more here.