0

I'm trying to build an app with devise which provides one sign in and sign out interface but multiple sign up interfaces depending on the model to sign up. Thus I came across polymorphic associations which fit my needs very well because I would like to have separate tables for the different models.

But I'm not able to sign up any user because I always get some error with the attributes of the base user model. I've read https://stackoverflow.com/a/11956734/1183192 and https://stackoverflow.com/a/15459313/1183192 and I think I adapted everything.

Base user model:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_type,
                  :salutation, :firstname, :lastname, :street, :zipcode, :city, :phone

  belongs_to :role, polymorphic: true

  def customer?
    'Customer' == self.role_type
  end

  def customer
    Customer.find(self.role_id) if self.customer?
  end

  def admin?
    'Admin' == self.role_type
  end

  def admin
    Admin.find(self.role_id) if self.admin?
  end
end

Customer model:

class Customer < ActiveRecord::Base
  has_one :user, as: :role
  attr_accessible :user_attributes
  accepts_nested_attributes_for :user
end

Customer controller:

class CustomersController < ApplicationController
  # removed all methods except new and create

  def new
    @customer = Customer.new
    @customer.build_user

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @customer }
    end
  end

  def create
    @customer = Customer.new(params[:customer])

    respond_to do |format|
      if @customer.save
        format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
        format.json { render json: @customer, status: :created, location: @customer }
      else
        format.html { render action: "new" }
        format.json { render json: @customer.errors, status: :unprocessable_entity }
      end
    end
  end
end

View (new.html.erb):

<h1>New customer</h1>

<%= form_for @customer do |f| %>

    <%= f.fields_for @customer.user do |u| %>

      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :email %>
          <%= u.email_field :email, required: true, autofocus: true %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :password %>
          <%= u.password_field :password, required: true %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :password_confirmation %>
          <%= u.password_field :password_confirmation, required: true %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :salutation %>
          <%= u.text_field :salutation %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :firstname %>
          <%= u.text_field :firstname %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :lastname %>
          <%= u.text_field :lastname %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :street %>
          <%= u.text_field :street %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :zipcode %>
          <%= u.text_field :zipcode %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :city %>
          <%= u.text_field :city %>
        </div>
      </div>
      <div class="row">
        <div class="small-12 large-12 columns">
          <%= u.label :phone %>
          <%= u.text_field :phone %>
        </div>
      </div>

    <% end %>

    <%= f.submit class: "button success" %>
<% end %>

The new page renders correct but when I try to submit I get the following error:

ActiveModel::MassAssignmentSecurity::Error in CustomersController#create
Can't mass-assign protected attributes: user

Parameters are:

{"utf8"=>"✓",
 "authenticity_token"=>"WngmLBR7MmVuhDyYxsASWQscUTB/VFmKmn/fdatVB30=",
 "customer"=>{"user"=>{"email"=>"max@mustermann.com",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]",
 "salutation"=>"",
 "firstname"=>"Max",
 "lastname"=>"Mustermann",
 "street"=>"Musterstraße 1",
 "zipcode"=>"12345",
 "city"=>"Musterstadt",
 "phone"=>"4917620289872"}},
 "commit"=>"Create Customer"}

I think the error is in the Customer class but I don't know how to fix it.

Update

I've made a change to the customer model:

class Customer < ActiveRecord::Base
  has_one :user, as: :role
  attr_accessible :user # :user instead of :user_attributes
  accepts_nested_attributes_for :user
end

Now I get the following error:

ActiveRecord::AssociationTypeMismatch in CustomersController#create
User(#70271634657140) expected, got ActiveSupport::HashWithIndifferentAccess(#70271609254480)

app/controllers/customers_controller.rb:44:in `new'
app/controllers/customers_controller.rb:44:in `create'
Community
  • 1
  • 1
stevecross
  • 5,588
  • 7
  • 47
  • 85

2 Answers2

1

Put in your view:

f.fields_for :user do |u|
#...

instead of

f.fields_for @customer.user do |u|

Error occurs because nested attributes root should be "user_attributes", not "user".

Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
0

May be it will help you replace attr_accessible :user_attributes To attr_accessible :user

in that customer model

Better ways:---

application.rb there is config.active_record.whitelist_attributes = true

Please refer Mass assignment protection

Thnaks in advance

Rajarshi Das
  • 11,778
  • 6
  • 46
  • 74
  • This gives me another error: ActiveRecord::AssociationTypeMismatch in CustomersController#create User(#70271634398080) expected, got ActiveSupport::HashWithIndifferentAccess(#70271609254480) – stevecross Jun 11 '13 at 13:38
  • config.active_record.whitelist_attributes is set to true – stevecross Jun 11 '13 at 13:40
  • 1
    This is association error mass assignment error will not be shown from now. Please check the association customer has_one :user so user belongs_to :customer but in your user model user belongs_to :role Thanks – Rajarshi Das Jun 12 '13 at 05:31