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 trialAnanya Jha
7,058 PointsPermit 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
Maciej Czuchnowski
36,441 PointsThis article looks promising:
http://kakimotonline.com/2014/03/30/extending-devise-registrations-controller/