0

I'm trying to implement a dual registration (users can be either customers or providers) with Devise, but I'm getting nowhere (>_<).

So I have a sign up link with a parameter http://localhost:3000/users/sign_up?type=customer and http://localhost:3000/users/sign_up?type=provider

My problem is that if I put the nested form with :provider like <%= f.fields_for :provider do |fp| %> as I expect it to be, because is an has_one association it isn't shown. And if I put it with :providers like <%= f.fields_for :providers do |fp| %> the field is properly shown in the form, but it is not saved.

I tried some of the proposed things in other posts (like this and this), but nothing seems to work for me...

Here is a simplified version of my code:

Routes:

Rails.application.routes.draw do
  devise_for :users, :controllers => { registrations: 'registrations' }
  resources :users
  resources :customers
  resources :providers
end

Models:

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

  has_one :customer
  accepts_nested_attributes_for :customer

  has_one :provider
  accepts_nested_attributes_for :provider
end

class Customer < ActiveRecord::Base
  belongs_to :user 
end

class Provider < ActiveRecord::Base
  belongs_to :user 
end

Controllers:

class RegistrationsController < Devise::RegistrationsController
  def sign_up_params
    params.require(resource_name).permit(:email, :password, :password_confirmation, customer: [:field_x], :provider: [:field_y]))
  end
end

Views:

<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  ...

  <% if params[:type] == "customer" %>
    <%= f.fields_for :customers do |fc| %>
      <div class="field">
        <%= fc.label :field_x %><br />
        <%= fc.text_field :field_x, autofocus: true %>
      </div>
    <% end %>
  <% end %>

  <% if params[:type] == "provider" %>
    <%= f.fields_for :providers do |fp| %>
      <div class="field">
        <%= fp.label :field_y %><br />
        <%= fp.text_field :field_y, autofocus: true %>
      </div>
    <% end %>
  <% end %>

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

Thanks a lot!

Community
  • 1
  • 1
Ellyster
  • 1
  • 1
  • Make sure your problem statement is clear. Your statement regarding `:providers` is clear, but your statement regarding `:provider` isn't so clear. – J0e3gan Jan 17 '15 at 19:13
  • when I use :provider the nested form doesn't show any field :( – Ellyster Jan 17 '15 at 21:01
  • Add this in your 'new' action of your controller: `resource.build_provider`. You can add an if statement to work with customers too. – Ryan K Jan 17 '15 at 21:44
  • How can I properly add `resource.build_provider` to the new action? It gives me an error if I try to do it after or before calling `super`. It seems that should be added between `build_resource({})` and `set_minimum_password_length` on the superclass method. – Ellyster Jan 18 '15 at 03:09

1 Answers1

0

When you are using fields_for :provider result is not displaying because you have not build it, build the association for nested attributes.
When you are using fields_for :providers record are not being save because in sign_up_params method you are not white listed providers attribute.
Also in strong parameter if you are using association(nested attribute) then you should use provider_attributes instead of provider.

Ashutosh Tiwari
  • 984
  • 6
  • 16