Additional parameters added in Devise not allowing user registration - ruby-on-rails

I'm currently running the following:
Rails 4.0.2
Devise 3.2.2
I've added three attributes to my user sign up form and also permitted the parameters in Devise in my application controller per the Devise documentation.
My problem now is that when I attempt to sign up I get the following error:
2 errors prohibited this user from being saved
Email can't be blank
Password can't be blank
I've permitted the additional parameters in my application controller as you can see below:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation) }
end
end
My user model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
And lastly my sign up form:
<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 :last_name %><br />
<%= f.text_field :last_name %></div>
<div><%= f.label :profile_name %><br />
<%= f.text_field :profile_name %></div>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
I've tried two different variations to allow the additional parameters but I am still getting the same error message. Any ideas that I can try?
Thank you

Run gem uninstall protected_attributes, then bundle install, then restart the rails server.
(I'm just posting sapmub's above comment as an answer. Thank you for your help sapmub!)

Related

custom password digest issue

I am trying to add hashed custom password into User model. What I did is:
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_user!
before_action :check_domain
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:slug, :custom_password_digest])
devise_parameter_sanitizer.permit(:account_update, keys: [:slug, :custom_password_digest])
end
end
new.html
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :slug %><br />
<%= f.text_field :slug %>
</div>
<div class="field">
<%= f.label :custom_password %><br />
<%= f.password_field :custom_password %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
class User
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
has_secure_password :custom_password
validates :slug, presence: true, uniqueness: true
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
I am getting error now:
https://i.stack.imgur.com/ILHjc.png
Could you please advise me what i am doing wrong?
Purpose is to save hashed custom_password to User table.
You're missing the field to store your encrypted password.
Create a migration to add it to the database...
rails g migration AddCustomPasswordDigestToUser custom_password_digest:string
then run the migration...
rails db:migrate

Problem saving custom attribute in rails devise gem

The authentication system in my app is handled by devise and now I want each user in my system to belong to an organisation. So each organisation will have multiple users.
When signing up, each user will select which organisation they want to join.
When a user is signing up, and they select and organisation from a combo-box, they get the following error:
ActiveRecord::AssociationTypeMismatch in Devise::RegistrationsController#create
Organisation(#70213198483780) expected, got "1" which is an instance of String(#70213152374240)
The following is what my source code looks like:
app/models/organisation.rb
class Organisation < ApplicationRecord
has_many :users
end
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :activities
belongs_to :organisation
end
app/views/devise/registrations/new.html.erb
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :organisation %><br />
<%= f.select :organisation, Organisation.all.collect { |o| [ o.organisation_name, o.id ] }%>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
before_action :configure_sign_up_params, if: :devise_controller?
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:organisation])
end
end
I suggest you should change in your form to
<%= f.select :organisation_id, Organisation.all.collect { |o| [ o.organisation_name, o.id ] }%>
Because the dropdown makes organisation.name as key and organisation.id as value.
Then change devise_parameter_sanitizer.permit(:sign_up, keys: [:organisation_id]) to allow organisation_id to be assigned to user
Instead of using collect on Organisation.all, use Organisation.all.pluck(:name, :id). It will give same result as but a more optimised query.

rails undefined method status

This is a very easy question I am using devise for authentication...So I am trying to modify my sign up .I am trying to add a radio button on my sign up but it is giving me error .undefined method `status' for User:0x00000001a66368. So i want to know why i can't use radio button on my sign up page
[registration/new.html.erb]
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %></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 >
<%= f.label 'InActive' do %>
<%= f.radio_button :status,'In Active'%>
<% end %>
</div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
[user.rb]
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
has_many :comments
validates :status,presence:true
validates :name, presence: true
def self.find_role(id)
User.find(id).roles
end
end
You need to add status field in the user table.
rails g migration add_user_status_to_user user_status:boolean
rake db:migrate
Then , In application controller, use strong parameters
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << [:user_status]
end
end
rails generate migration add_status_to_user status:boolean
rake db:migrate
You need to by pass Strong Parameters to add additional new attributes to the sign up page.
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up).push(:status)
end
end

rails devise user external api

I am trying to setup a newsletter signup procedure when a new user signs up. I am using Mailchimp via gibbon to handle the newsletters. I have added a subscribe attribute to my model and a getter and setter method. I also have added the subscribe checkbox to my form. What I need to do is if the form box is checked subscribe the user to the email on creation.
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, :username, :subscribe
validates :username, presence: true
validates_uniqueness_of :username
has_many :contest_entries, dependent: :destroy
has_many :votes, dependent: :destroy
def subscribe=(join)
puts "called subscribe with #{join}"
if join
Gibbon.new.list_subscribe(:id => "blah", :email_address => self.email)
end
end
def subscribe
subscribe ||= false
end
end
Form view
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :username %><br />
<%= f.text_field :username %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :subscribe, "Subscribe to Newsletter?" %><br />
<%= f.check_box :subscribe, :checked => true %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
I was hoping that by adding the attr_accessible and a method it would call the api from the contoller automatically, but it does not seem to be called.
Any advice on how to handle this? I could also use advice on how to test with RSPEC to make sure it is being called.
Thanks,
Cory
Ok I figured out the issue. The problem was with the check for join inside the setter method. Since it was a checkbox, I needed to check for a matching integer of 1.
def subscribe=(join)
begin
if join.to_i == 1
gb = Gibbon.new
result = gb.list_subscribe(:id => "blah", :email_address => self.email)
end
rescue
false
end
end

rails devise: user and account model

Hi I am trying to customize the sign up page by adding an additional field, name.
This is done by adding a Profile model to my app.
class Profile < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :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, :profile_attributes
has_one :profile, :dependent => :destroy
accepts_nested_attributes_for :profile
end
I overrode the registration model:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
profile = #user.build_profile
end
def create
super
end
def update
super
end
end
And my new sign up page:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><% f.fields_for :profile do |builder| %>
<p><%= builder.label :name %></p>
<p><%= builder.text_field :name %></p>
<% end %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "links" %>
However, I am not sure if everything else works, but the registration page still looks the same. That is, it doesn't show the name input field. How do I fix this?
What am I missing?
I suspect you did not generate the views. Did you run the following?
rails generate devise:views
More information on changing views can be found in "Configuring views" on the devise wiki:
https://github.com/plataformatec/devise
Thanks,
Tabrez

Resources