Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Permit parameters for nested forms in devise registration

I have added nested forms to devise registration controller.

There are 2 types of users in my application. The User model has a polymorphic association to 'Students' and 'Professors' (types of users).

The models are as follows

User

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

  belongs_to :loginable, polymorphic: true, validate: true
  accepts_nested_attributes_for :loginable
end

Professor

class Professor < ActiveRecord::Base
  has_and_belongs_to_many :colleges
  has_one :user, as: :loginable, dependent: :destroy
end

Student

class Student < ActiveRecord::Base
  belongs_to :college
  has_one :user, as: :loginable, dependent: :destroy
end

The devise registration form in as follows

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
    <%= devise_error_messages! %>

    <div>
      <%= f.label :first_name %><br />
      <%= f.text_field :first_name, autofocus: true %>
    </div>

    <div>
      <%= f.label :middle_name %><br />
      <%= f.text_field :middle_name %>
    </div>

    <div>
      <%= f.label :last_name %><br />
      <%= f.text_field :last_name %>
    </div>

    <div>
      <%= f.label :email %><br />
      <%= f.email_field :email %>
    </div>

    <div>
      <%= f.label :password %>
      <% if @validatable %>
          <i>(<%= @minimum_password_length %> characters minimum)</i>
      <% end %><br />
      <%= f.password_field :password, autocomplete: "off" %>
    </div>

    <div>
      <%= f.label :password_confirmation %><br />
      <%= f.password_field :password_confirmation, autocomplete: "off" %>
    </div>

    <div id="select_type">
      <%= f.label :user_type %><br />
      <%= f.select :loginable_type, options_for_select(%w[Professor Student]) %>
    </div>

    <div id="student_reg">
      <%= f.fields_for Student.new do |rf| %>
          <%= render :partial => "students/form", :locals => { :f => rf } %>
      <% end %>
    </div>

    <div id="prof_reg">
      <%= f.fields_for Professor.new do |rf| %>
          <%= render :partial => "professors/form", :locals => { :f => rf } %>
      <% end %>
    </div>

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

<%= render "devise/shared/links" %>

The partials are as follows

Student

<%= f.label :registration_number %><br />
<%= f.text_field :reg_number %>

Professor

<%= f.label :degree %><br />
<%= f.text_field :degree %>

The devise registration controller is as follows

class RegistrationsController < Devise::RegistrationsController

  def create
    build_resource(sign_up_params)

    if resource.loginable_type == 'Professor'
      resource.loginable = Professor.new
    else
      resource.loginable = Student.new
    end

    resource_saved = resource.save
    yield resource if block_given?
    if resource_saved
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_flashing_format?
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      @validatable = devise_mapping.validatable?
      if @validatable
        @minimum_password_length = resource_class.password_length.min
      end
      respond_with resource
    end
  end

  def destroy
    resource.loginable.destroy
    Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
    set_flash_message :notice, :destroyed if is_flashing_format?
    yield resource if block_given?
    respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
  end

  private

  def sign_up_params
    params.require(:user).permit(:first_name, :middle_name, :last_name, :email, :password, :password_confirmation, :loginable_type, :student => [:reg_number], :professor => [:degree])
  end

  def account_update_params
    params.require(:user).permit(:first_name, :middle_name, :last_name, :email, :password, :password_confirmation, :current_password)
  end
end

I have added permit for student and professor but it shows unknown parameter error.

The hash that is passed is

Parameters: {"utf8"=>"✓", "authenticity_token"=>"jgKWffTYv+axMkv9RySUT90xcT3scNqQWKMf6006c94=", "user"=>{"first_name"=>"Ananya", "middle_name"=>"", "last_name"=>"", "email"=>"ananyahjha93@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "loginable_type"=>"Student", "student"=>{"reg_number"=>"2012018"}, "professor"=>{"degree"=>""}}, "commit"=>"Sign up"} Unpermitted parameters: student, professor

In case I change the syntax, It shows unpermitted parameters .

I have tried changing to " student: [ :reg_number ] " or " student_attributes: [ :reg_number ] " but it does work.

Also tried adding

before_filter :update_sanitized_params, if: :devise_controller?

def update_sanitized_params
    devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:first_name, :middle_name, :last_name, :email, :password, :password_confirmation, :loginable_type, student: [:reg_number], professor: [:degree])}
  end

1 Answer