Not passing params to action with form_for - ruby-on-rails

I can't figure out why my form is not passing params to the registration controller. I have a registration form that doubles as a login form using jquery and javascript. My second form (the last one) is supposed to send over registration info to the registration controller. Unfortunatly I keep getting wrong number of arguments (0 for 1). I'm not sure how I'm not passing the information in, any help is appreciated.
new.html.erb
<div id="imageDisplay"></div>
<div class="login-switch">
<div id="login-div" class="button button-outline button-calm switches active-button">
LOG IN
</div>
<div id="signup-div" class="button button-outline button-calm switches">
SIGN UP
</div>
</div>
<%= form_for(#user, url: sessions_path, html: {id: "sign-in-form"}) do |f| %>
<div class="list list-inset">
<label id="sign-up-input" class="item item-input">
<%= f.email_field :username, autofocus: true %>
</label>
<label id="sign-up-input" class="item item-input">
<%= f.password_field :password, autocomplete: "off" %>
</label>
<%= f.submit "Log in", class: "button button-block button-calm" %>
</div>
<% end %>
<%= form_for(#user, url: registrations_path, html: {id: "sign-up-form"}) do |f| %>
<div class="list list-inset">
<div id="part-1">
<!-- part one of sign up -->
<label id="sign-up-input" class="item item-input">
<%= f.email_field :email, autofocus: true, placeholder: "E-mail" %>
</label>
<label id="sign-up-input" class="item item-input">
<%= f.password_field :password, autocomplete: "off", placeholder: "Password" %>
</label>
<label id="sign-up-input" class="item item-input">
<%= f.password_field :password_confirmation, autocomplete: "off",placeholder: "Confirm password" %>
</label>
<div id="slide-part-2" class="button button-block button-calm">Next</div>
</div>
<div id="part-2">
<!-- part two of sign up -->
<%= f.file_field :avatar, id: "fileInput"%>
<label id="sign-up-input" class="item item-input">
<%= f.text_field :username, autofocus: true, placeholder: "username" %>
</label>
<%= f.submit "Sign up", class: "button button-block button-calm" %>
</div>
<% end %>
</div>
</div>
registrations_controller.rb
class RegistrationsController < ApplicationController
[![enter image description here][1]][1] def new
end
def create
#user = User.create(sign_up_params)
if #user.save
log_in #user
flash[:success] = "We Made it!"
else
flash[:error] = #user.errors
end
end
private
def sign_up_params
params.require.(:user).permit(:email, :username, :avatar, :password, :password_confirmation, :trump)
end
end

Remove . after params.require:
def sign_up_params
params.require(:user).permit(:email, :username, :avatar, :password, :password_confirmation, :trump)
end

The error says wrong number of arguments(0 for 1), it's because you didn't pass any argument in the require method, you added a . before the opening parenthesis for the argument, you need to remove it, because Ruby is executing (:user) as a method but its not. Fix this error by correcting the typo as dp7 mentioned in his answer
def sign_up_params
params.require(:user).permit(:email, :username, :avatar, :password, :password_confirmation, :trump)
end
Hope that helps!

It should be like that :
def sign_up_params
params.require(:user).permit(:email, :username, :avatar, :password, :password_confirmation, :trump)
end

Related

How to show validation errors for a login form when fields are empty on submit

I'm using the Devise gem for authentication and for the login form when I click on "Log in" with the fields blank I get the error "Invalid Email or password". I think it would be nice just like the registration form to have errors like "Name can't be blank" or "Email can't be blank" depending on the field that is blank. How can one achieve that?
Log in view
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: false }) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "current-password" %>
</div>
<% if devise_mapping.rememberable? %>
<div class="field remember">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
before_action :update_allowed_parameters, if: :devise_controller?
def after_sign_up_path_for(_resource)
groups_path
end
def after_sign_in_path_for(_resource)
groups_path
end
protected
def update_allowed_parameters
devise_parameter_sanitizer.permit(:sign_up) do |u|
u.permit(:name, :email, :password, :password_confirmation)
end
devise_parameter_sanitizer.permit(:account_update) do |u|
u.permit(:name, :email, :password, :password_confirmation, :current_password)
end
end
end
Its pretty trivial to just add a client side validation which will provide immediate feedback if you want to:
# app/views/devise/sessions/new.html.erb
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", required: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "current-password", required: true %>
</div>
<% if devise_mapping.rememberable? %>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>`
The views in your application will take priority over those defined by the engine.
The reason why Devise doesn't actually use model validation at all for sessions is that models are not context aware and adding this feature would add a lot of complexity for very little gain.
Your model doesn't have a concept of "signing in" so if you called resource.valid? it will fire all the validations for creating a record like for example uniqueness of the email.
While you could do this by creating a form object or by overriding the controller method and adding the errors "inline" it provides very little additional value in safeguarding your application against bad user input which is what server side validations are primarily intendended to do (user feedback is the secondary purpose). YAGNI.

validates_confirmation_of :password does not work [ruby 4.2]

validates_confirmation_of :password does not work when I submitted my form. Even if the password confirmation is not the same, the user is signed up.
I wrote the same thing that the guide. during my research , I did not found anything that explain that.
Do you know what is happening and how can I solve it?
Here is my code:
My view:
<%= form_for User.new do |f| %>
<div class="row">
<div class="col-md-6">
<%= f.label :Prénom %> :
<%= f.text_field :first_name, class: "form-control" %><br />
</div>
<div class="col-md-6">
<%= f.label :Nom %> :
<%= f.text_field :last_name, class: "form-control" %><br />
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :Pseudo %> :
<%= f.text_field :user_name, class: "form-control"%><br />
</div>
<div class="col-md-6">
<%= f.label :Email %> :
<%= f.email_field :email, class: "form-control" %><br />
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :Mot_de_passe %> :
<%= f.password_field :password, class: "form-control" %><br />
</div>
<div class="col-md-6">
<%= f.label :Confirmation_mot_de_passe %> :
<%= f.password_field :password_confirmation, class: "form-control" %><br />
</div>
</div>
<%= f.label :Club_favori %> :
<%=f.select(:club) do%>
<%= options_from_collection_for_select(Club.all,:id ,:name) %>
<% end %>
<br>
<%= f.submit class: "btn btn-primary" %>
<% end %>
My model:
class User < ActiveRecord::Base
has_merit
has_secure_password
has_many :comments
validates_length_of :password, minimum: 5, too_short: 'please enter at least 5 characters', on: :create
validates_presence_of :user_name, :message => 'Vous devez remplir tout les champs.', on: :create
validates_uniqueness_of :user_name, :case_sensitive => false, :message => "Ce pseudo n'est pas disponible.", on: :create
validates_confirmation_of :password, on: :create
end
My controller:
class UsersController < ApplicationController
def create
#user = User.new(user_params)
if #user.save
#user.add_badge(1)
session[:user_id] = #user.id
redirect_to '/feed'
else
redirect_to '/signup', flash: {error_message: #user.errors}
end
end
private
def user_params
params.require(:user).permit( :user_name, :first_name, :last_name, :email, :password, :sash, :club)
end
def new
#user = User.new
#clubs =Club.all
end
end
Thank you in advance for your help.
You override your current #user when you enter your form.
Just change:
<%= form_for User.new do |f| %>
to
<%= form_for #user do |f| %>

TypeError in Devise::RegistrationsController#create

For Devise with Rails 4.2., I am able to sign up users when I turn off confirmation required in my user model but when I turn it back on I get this error.
no implicit conversion of Array into String <
# i.e. OpenSSL::Digest::SHA1#block_length
def generate_key(salt, key_size=64)
OpenSSL::PKCS5.pbkdf2_hmac_sha1(#secret, salt, #iterations, key_size)
end
end
referring to this line
devise (3.5.10) lib/devise/token_generator.rb:50:in `pbkdf2_hmac_sha1'
I am using mailtrap for my development settings and I am able to get mail in my contact page.
In my user.rb I have
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
My devise initalizer is set exactly the same as another project that works.
In my application controller, I have set parameters
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:firstname, :lastname, :email, :avatar, :password, :password_confirmation) }
end
My views/devise contain the folders (confirmations, mailer, passwords, registrations, sessions, shared, and unlocks.
My devise registrations new is below:
<div class="row">
<%= bootstrap_devise_error_messages! %>
<div class="panel panel-default devise-bs">
<div class="panel-heading">
<h4><%= t('.sign_up', :default => "Sign up") %></h4>
</div>
<div class="panel-body">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), html: { role: "form" }) do |f| %>
<div class="form-group">
<%= f.label :firstname %>
<%= f.text_field :firstname, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :lastname %>
<%= f.text_field :lastname, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :avatar %><br>
<%= f.file_field :avatar, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
<%= f.submit t('.sign_up', :default => "Sign up"), class: "btn btn-primary" %>
<% end %>
</div>
<div class="panel-footer">
<%= render "devise/shared/links" %>
</div>
</div>
Any tips on what I could be doing wrong, I have spun my wheels for a couple of days.
Thanks :)
Check that your to_json/as_json in your user.rb is working properly.

Rails trying to create a user when updating user details

I'm learning rails and building an authentication system using guides from around the web and following railscasts tutorials.
I've come to a stand still at the moment and need a bit of assistance if possible.
When ever I try to edit the user profile, I get an error message which tells me that it can't create an account due to fields such as email and username already being taken.
Looking around it seems it's related to how my edit form is being submitted, but I can't solve it!
Any help would be appreciated.
Users_controller.rb
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
edit.html.erb
<%= form_for :user, url: '/users' do |f| %>
<form class="m-t" role="form" action="#">
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', autocomplete: "off" %>
</div>
<div class="form-group">
<%= f.label :user_type %>
<%= f.select(:user_type, ['Admin', 'Technical', 'Accounts'], {}, { :class => 'form-control' }) %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :telephone %>
<%= f.text_field :telephone, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :mobile %>
<%= f.text_field :mobile, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :user_name %>
<%= f.text_field :user_name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :company_admin%>
<%= f.check_box :company_admin, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :user_admin %>
<%= f.check_box :user_admin, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :emergency_contact %>
<%= f.check_box :emergency_contact, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.submit "Submit", class: "btn btn-primary block full-width m-b" %>
</div>
</form>
<% end %>
Rails Log
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'emailaddress#gmail.com' LIMIT 1
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."user_name" = 'AUserName' LIMIT 1
user.rb
class User < ActiveRecord::Base
has_secure_password
validates :name, presence: { message: "Please enter your name." }
validates_uniqueness_of :email, presence: { message: "Please enter your email address." }
validates_format_of :email, with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z] {2,})\z/i, message: "Please enter a valid email address.", allow_blank: true
validates :telephone, presence: { message: "Please enter your phone number." }
validates :mobile, presence: { message: "Please enter your mobile number." }
validates_uniqueness_of :user_name, presence: { message: "Please enter your user name." }
validates_confirmation_of :password, presence: { message: "Please enter your password" }, allow_nil: true
before_create { generate_token(:auth_token) }
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
end
Wait I'm wrong on the validation. Just spotted it.
<%= form_for :user, url: '/users' do |f| %>
This won't use the #user object, which means rails thinks you're trying to create a user.
Switch it to
<%= form_for #user do |f| %>
Rails will also infer the correct place to post to so you won't need the url option anymore.

Validates "presence true" works with edit page but wont work with sign up page

This is my first question here and im a newbie in rails. I have a weird problem.
I was following One Month Rails course and I added :name column to DB for user and wanted each new user to have Name while registering and also beign able to change his name while accessing the Edit Page. I added that to devise and wanted to validate so it can't be blank.
The problem is that Edit page works fine (says properly when it's blank and allows for name change) but the Sign Up page ALWAYS says "Name can't be blank" and forbids from creating new user. I have no idea why it is happening, anyone could help?
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:account_update) << :name
end
end
Here i added Validates in user class:
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 :vins, dependent: :destroy
validates :name, presence: true
end
This is sign up page:
<div class="panel panel-default">
<div class="panel-heading">
<h2>Sign up</h2>
</div>
<div class="panel-body">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Sign up", class: "btn btn-primary" %>
</div>
<% end %>
<div class="btn btn-default btn-sm">
<%= render "devise/shared/links" %>
</div>
</div>
</div>
And edit page:
<div class= "panel panel-default">
<div class="panel-heading">
<h2>Edit <%= resource_name.to_s.humanize %></h2>
</div>
<div class= "panel-body">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="form-group">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Update", class: "btn btn-primary" %>
</div>
<% end %>
<div class= "panel-footer">
<%= link_to "Back", :back %>
</div>
</div>
</div>
Your problem seems to be that you're defining the configure_permitted_parameters twice in your ApplicationController. So the first definition gets overwritten by the second, and thus the :name parameter is not passed to the sign_in method through the sanitation. So simply combining the method definition should get rid of the problem.
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
devise_parameter_sanitizer.for(:account_update) << :name
end

Resources