Rails (param is missing or the value is empty) - ruby-on-rails

I am using rails 4 and I've read that attr_accessible is beter not to use in this version. I have created that code:
class UsersController < ApplicationController
def new
#user = User.new(user_params)
end
private
## Strong Parameters
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
But it gives me out this error:
ActionController::ParameterMissing in UsersController#new
param is missing or the value is empty: user
I am trying to display that html.erb:
<%= form_for :user do |f| %>
<%= f.text_field :name %>
<%= f.text_field :email %>
<%= f.text_field :password %>
<%= f.text_field :password_confirmation %>
<%= f.label :submit %>
<% end %>
Any solutions?

Typically the new action would be #user = User.new as there are no user_params getting posted back from the view.

class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to user_path(#user)
else
render :action => 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
Basically while instantiating an object, you don't need to call user_params .

Related

Upon submitting sign up form, ActiveModel::ForbiddenAttributesError

I've created a sign up form on rails, and upon clicking my submit button to save my user details, I get the following error:
ActiveModel::ForbiddenAttributesError
for this line: #user = User.new(params[:user])in my users controller.
See code below:
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
end
render "new"
end
end
new.html.erb
<%= form_for(:user, :url => {:controller => 'users', :action => 'create'}) do |f| %>
</br> <%= f.text_field :firstname, placeholder: 'First Name' %>
</br> <%= f.text_field :lastname, placeholder: 'Last Name' %>
</br> <%= f.text_field :email, placeholder: 'Email' %>
</br> <%= f.password_field :password, placeholder: 'Password' %>
</br> <%= f.password_field :password_confirmation, placeholder: 'Confirm Password' %>
<%= f.submit :Register %>
<% end %>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
routes.rb
Rails.application.routes.draw do
get 'users/new'
get 'pages/home'
get 'pages/howitworks'
get 'pages/about'
get 'pages/contact'
get 'pages/becomeauser'
get 'signup' => 'users#new'
resources :users
The params[:user] hash might have attributes in it that isn't a part of the User model. In your case, i'm guessing its password_confirmation.
Use strong params the next time - here
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
end
render "new"
end
end
private:
def user_params
params.require(:user).permit(:first_name, :last_name, :email, : password)
end
This means that you have Strong Parameters enabled. I would encourage you to read at least a part of this Rails Guide. Essentially, instead of using params[] to update or create records, you should use an intermediate method to ensure that users aren't sneaking information into your requests. This is much safer. For instance, someone could submit a "created_at" attribute with your form, and then be modifying fields which are not supposed to be edited. Your approach should instead be as follows:
Create a private user_params method in the controller which permits specified attributes
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
Replace your User.create(), User.new(), and User.update() references to params[:user] with user_params
# Do this instead of #user = User.new(params[:user])
#user = User.new(user_params)

Can't log in to my database. Error: "Param is missing or the value is empty: user"

I'm having a trouble with my logging in. It highlights the user_params function as an error in users controller. What could it be?
/views/sessions/new.html.erb or login form
<h1>Log In</h1>
<%= form_tag users_path do %>
<div class="field">
<%= label_tag :email %><br />
<%= text_field :email, params[:email] %>
</div>
<div class="field">
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</div>
<div class="actions"><%= submit_tag "Log In" %></div>
<% end %>
controllers/sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, notice: "Logged In!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to signup_path, notice: "Logged out!"
end
end
controllers/users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to user_tasks, notice: "Thank you for signing up!"
else
render "new"
end
end
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
end
controllers/application_controller.rb
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
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
def authorize
redirect_to login_url, alert: "Not authorized" if current_user.nil?
end
end
rake routes
Generated parameters
{"utf8"=>"✓", "authenticity_token"=>"jtdA0rITCiFjU9ECiKnDUMh/MHMpqv6u+Bd65PAfpARwYsmb9Dli32wpULfmYa7wpBQiFYxAGHF6flCfJgPOew==", "email"=>"dsadsa", "password"=>[FILTERED]", "commit"=>"Log In"}
Any help?
change this line and try please.
<%= text_field :email, params[:email] %>
to
<%= text_field_tag :email, params[:email] %>
Also majorly add this in your routes file to redirect it to sessions controller create action.
post '/authenticate' => 'sessions#create'
change this tag
<%= form_tag users_path do %>
to
<%= form_tag /authenticate do %>
When you look into the params, they are not coming from the user. Try changing your user_params like below
def user_params
params.permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
I suggest you keep the :user namespace for params in your form
<%= form_tag users_path do |form| %>
<%= fields_for :user do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email, params[:email] %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="actions"><%= submit_tag "Log In" %></div>
<% end %>
<% end %>
So you can still use params.require(:user) in your controller as usual
Parameters will look like this
{
"utf8"=>"✓",
"authenticity_token"=>"jtdA0rITCiFjU9ECiKnDUMh/MHMpqv6u+Bd65PAfpARwYsmb9Dli32wpULfmYa7wpBQiFYxAGHF6flCfJgPOew==",
"user" => {
"email"=>"dsadsa",
"password"=>[FILTERED],
},
"commit"=>"Log In"
}

Adding Email Confirmation to Rails App

I followed Michael Hartl's tutorial up to a point, then followed Ryan Bates' Railcast for adding reset password (#274). Perhaps "tried to follow" is more accurate since I can't get the reset password to work despite many hours of effort/searching/tial&error.
Had to deviate from Ryan's call: #user.update_attributes(params[:user]) to: #user.update_attributes(user_params) as I was getting a ForbiddenAttributesError.
I also had to comment-out the #validates :password, length: { minimum: 6 } in the User class as it failed on submission (even though the submitted password was greater than 6 in length).
The code doesn't currently generate any errors, and the redirect_to root_url, :notice => "Password has been reset!" works. However, the password is not updated in the db.
Any insight is very gratefully received.
app/models/user.rb
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
has_secure_password
#validates :password, length: { minimum: 6 }
before_create :create_remember_token
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.digest(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64(40)
end while User.exists?(column => self[column])
end
def create_remember_token
self.remember_token = User.digest(User.new_remember_token)
end
end
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params) if #user.save
sign_in #user
flash[:success] = "Welcome!"
redirect_to #user
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, :password_reset_token)
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
end
app/controllers/password_resets_controller.rb
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
redirect_to root_url, :notice => "Email sent with password reset instructions."
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
def update
#user = User.find_by_password_reset_token!(params[:id])
if #user.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, :alert => "Password reset has expired."
elsif #user.update_attributes(user_params)
redirect_to root_url, :notice => "Password has been reset!"
else
render :edit
end
end
private
def user_params
params.require(:user).permit(:id, :name, :email, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at)
end
end
app/views/password_resets/edit.html.erb
<%= form_for #user, :url => password_reset_path(params[:id]) do |f| %>
<% if #user.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</div>
<div class="actions"><%= f.submit "Update Password" %></div>
<% end %>
app/views/password_resets/new.html.erb
<h1>PasswordReset#new</h1>
<%= form_tag password_resets_path, :method => :post do %>
<div class="field">
<%= label_tag :email %>
<%= text_field_tag :email, params[:email] %>
</div>
<div class="actions"><%= submit_tag "Reset Password" %></div>
<% end %>
There is no model for password_resets.
In app/views/password_resets/edit.html.erb, your form describes :password and :password_confirmation. However, in your PasswordResetsController, you update using user_params, which describe :id, :name, :email, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at. Note the lack of the attributes you are trying to set. In the console, you will probably see a message indicating that the desired attributes have been discarded. Many of the attributes that you have added to user_params do not make sense in any context, as they would never be set by the user in any circumstance, like :id, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at. In fact, may of these are blatant security risks (do you want the user to decide if they are an admin?). You will probably have better luck if you change the user_params method in PasswordResetsController to look like:
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
Make sense?

Added Bio field to 'edit profile' - created migration but then what to add to model?

I've followed Hartl's rails tutorials to the of Chap 9 and now i'm building my own idea so i can get deep into rails.
Current issue - I've added a Bio filed to user profiles in edit and the text box appear on the Users profile but i can't figure out how to save the text added to the Bio text box. I've generated a migration called "add_bio_to_user_profile" (haven't raked yet) but i'm struggling to figure out what to add to the User.rb model. Does controller come into this to?
Migration "add_bio_to_user_profile"
class AddBioToUserProfile < ActiveRecord::Migration
def change
add_column :user_profiles, :, :string
end
end
Model/User.rb
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
#VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
#format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
controllers/user_controller.rb
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.find(params[:id])
end
def new
#user = User.new
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_url
end
def create
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
show.html.erb
<% provide(:title, #user.name) %>
<div class="row">
<aside class="span4">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
<div>
<textarea rows="3"></textarea>
</div>
</aside>
</div>
edit.html.erb
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :bio %>
<textarea rows="3"></textarea>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
<%= gravatar_for #user %>
change
</div>
</div>
Formally, you dont have to do anything. Rails magic starts here. You run the migration, restart server if you are running production env, change the name of textbox to :bio in edit html.erb
<%=f.text_field :bio%>
When this form is submitted, it automatically gets saved in the table. Additionally, you can add validation on this field in model.
In edit.html.erb, make this change
<%= f.label :bio %>
<%=f.text_field :bio%>
and in show.html.erb
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
Bio: <%= #user.bio %>
One change in controller.rb
def user_params
params.require(:user).permit(:name, :email, :bio, :password,
:password_confirmation)
end
You want to add bio field to users table I guess.
Here is the migration.
class AddBioToUserProfile < ActiveRecord::Migration
def change
add_column :users, :bio, :string
end
end
While you are going for a migration, only model comes to play. and in this,
users is your table name and bio is the new column and string is the data-type.

Can't mass-assign protected attributes with ruby-on-rails

I am trying to have a nested form on my users/new page, where it accepts user-attributes and also company-attributes. When you submit the form:
Here's what my error message reads:
ActiveModel::MassAssignmentSecurity::Error in UsersController#create
Can't mass-assign protected attributes: companies
app/controllers/users_controller.rb:12:in `create'
Here's the code for my form:
<%= form_for #user do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.fields_for :companies do |c| %>
<%= c.label :name, "Company Name"%>
<%= c.text_field :name %>
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<br>
<% if current_page?(signup_path) %>
<%= f.submit "Sign Up", class: "btn btn-large btn-primary" %> Or, <%= link_to "Login", login_path %>
<% else %>
<%= f.submit "Update User", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
Users Controller:
class UsersController < ApplicationController
def index
#user = User.all
end
def new
#user = User.new
end
def create
#user = User.create(params[:user])
if #user.save
session[:user_id] = #user.id #once user account has been created, a session is not automatically created. This fixes that by setting their session id. This could be put into Controller action to clean up duplication.
flash[:success] = "Your account has been created!"
redirect_to tasks_path
else
render 'new'
end
end
def show
#user = User.find(params[:id])
#tasks = #user.tasks
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = #user.name.possessive + " profile has been updated"
redirect_to #user
else
render 'edit'
end
#if #task.update_attributes params[:task]
#redirect_to users_path
#flash[:success] = "User was successfully updated."
#end
end
def destroy
#user = User.find(params[:id])
unless current_user == #user
#user.destroy
flash[:success] = "The User has been deleted."
end
redirect_to users_path
flash[:error] = "Error. You can't delete yourself!"
end
end
Company Controller
class CompaniesController < ApplicationController
def index
#companies = Company.all
end
def new
#company = Company.new
end
def edit
#company = Company.find(params[:id])
end
def create
#company = Company.create(params[:company])
#if #company.save
#session[:user_id] = #user.id #once user account has been created, a session is not automatically created. This fixes that by setting their session id. This could be put into Controller action to clean up duplication.
#flash[:success] = "Your account has been created!"
#redirect_to tasks_path
#else
#render 'new'
#end
end
def show
#comnpany = Company.find(params[:id])
end
end
User model
class User < ActiveRecord::Base
has_secure_password
attr_accessible :name, :email, :password, :password_confirmation
has_many :tasks, dependent: :destroy
belongs_to :company
accepts_nested_attributes_for :company
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }
#below not needed anymore, due to has_secure_password
#validates :password_confirmation, presence: true
end
Company Model
class Company < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :users
end
First for debugging put the bang on the create in the two controllers like so: create! Your log may spit out more.
Then, if that sucked, try it the old fashioned way of Building the two Objects and assigning each one with the params.
I assume also that this is it for attributes, no after saves that should have more to the schema then you are showing.
Lastly, you are missing
def new
#user = User.new
#company = #user.companies.build
end
Print out the params too, just in case it says something wonky but adding this line: as #Beerlington said should work too :company_attributes, maybe companies_attributes... spit balling here.
Add attr_accessible :companies to your user model attr list

Resources