how to set foreign key through the controller in rails? - ruby-on-rails

I've got an address form nested into a user form but cant get the foreign key to fill. I've seen people suggest using a hidden field, but that seems to be a bad idea from a security standpoint. How exactly do you set the foreign key using the controller? Right now I'm getting Address user can't be blank error when I try to submit
MVC below
user\new.html.erb
<div>
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :rank %>
<%= f.text_field :rank %>
<%= f.label :firstName, "First Name" %>
<%= f.text_field :firstName %>
<%= f.label :lastName, "Last Name" %>
<%= f.text_field :lastName %>
<%= f.label :middleInitial, "Middle Initial" %>
<%= f.text_field :middleInitial %>
<%= fields_for :address do |a| %>
<%= a.label :address %>
<%= a.text_field :address %>
<%= a.label :city %>
<%= a.text_field :city %>
<%= a.label :state %>
<%= a.text_field :state %>
<%= a.label :zip, "Zip Code" %>
<%= a.text_field :zip %>
<% end %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :dateOfBirth, "Date of Birth" %>
<%= f.text_field :dateOfBirth %>
<%= f.label :MOS, "MOS" %>
<%= f.text_field :MOS %>
<%= f.label :ets_pcsDate, "ETS/PCS Date" %>
<%= f.text_field :ets_pcsDate %>
<%= f.label :phoneNum, "Phone Number" %>
<%= f.text_field :phoneNum %>
<%= f.label :password %>
<%= f.text_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.text_field :password_confirmation %>
<%= f.submit "Sign up" %>
<% end %>
</div>
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>
Models
User
class User < ActiveRecord::Base
attr_accessible :MOS, :dateOfBirth, :ets_pcsDate, :firstName,
:lastName, :middleInitial, :phoneNum, :rank, :email, :password,
:password_confirmation
has_secure_password
has_one :address, dependent: :destroy
accepts_nested_attributes_for :address
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
validates :rank, presence: true
validates :firstName, presence: true, length: { maximum: 15 }
validates :lastName, presence: true, length: { maximum: 20 }
validates :middleInitial, presence: true, length: { maximum: 1 }
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 :dateOfBirth, presence: true
validates :MOS, presence: true
validates :ets_pcsDate, presence: true
validates :phoneNum, presence: true
validates :password, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Address
class Address < ActiveRecord::Base
attr_accessible :address, :city, :state, :zip
belongs_to :user
validates :address, presence: :true
validates :city, presence: :true
validates :state, presence: :true
validates :zip, presence: true
validates :user_id, presence: true
end
Controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :show, :destory]
before_filter :correct_user, only:[:edit, :update]
before_filter :admin_user, only: :destroy
def new
#user = User.new
#user.address.build
end
def create
#user = User.new(params[:user])
#address = #user.build_address(params[:address])
if #user.save
sign_in #user
flash[:success] = "Welcome to B Troop!"
redirect_to #user
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
def index
#users = User.paginate(page: params[:page])
end
def edit
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User removed"
redirect_to users_path
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to root_path, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end

Removing the user_id validation did the trick.

Related

Password confirmation in Rails 5

This is my view:
<%=form_for [:admin, #user] do |f|%>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<%=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%>
<%=f.submit "Submit" %>
<%end%>
Controller code for adding user:
def create
#user = User.new(user_params)
if #user.save
redirect_to admin_users_path
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password)
end
These are validations in the model:
validates :name, presence: true
validates :email, presence: true
validates :password, presence: true
validates :password, confirmation: { case_sensitive: true }
But confirmation password doesn't work.
Validation works for all (they are required) form elements, except second password input - password_confirmation which can be different from first password input.
User is added to the database even if second password input is empty, because in the validation rules, there is no rule for that .
What am I doing wrong ?
You need to add password_confirmation to user_params in the controller.
I.e.
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
Try: validates_confirmation_of :password
Model:
class Person < ActiveRecord::Base
validates_confirmation_of :user_name, :password
validates_confirmation_of :email_address, :message => "should match confirmation"
end
View:
<%= password_field "person", "password" %>
<%= password_field "person", "password_confirmation" %>
You could take a look to the validates_confirmation_of.

Ruby on Rails, require old password to change password

I have implemented a user authentication system in rails using the gem 'bcrypt';I would like to insert a current password field to the edit form to make the changes to the password.
How can do this?
class User < ActiveRecord::Base
before_save { self.email = email.downcase}
before_create :create_remember_token
#Associations
has_one :profile
has_many :posts
#validations
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.digest(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.digest(User.new_remember_token)
end
end
<% 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 :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 %>
</div>
</div>
Thank you
In your view file:
<%= f.label :current_password %>
<%= f.password_field :current_password %>
Also make sure you permit the current_password parameter in your controller.
I assumed current_password attr is already defined by has_secured_password.

"Password confirmation" message not showing up when both password fields are empty

Working through the railstutorial.org . Currently on the Update Profile page part of it. When leaving the Password and Password Confirmation fields empty, only the Password is too short error comes up, though in the tutorial screenshot Password confirmation can't be blank message is present. But, it does show up when the Password field is filled and Password Confirmation field is left empty.
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 :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>
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
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
.
.
.
user.rb:
class User < ActiveRecord::Base
has_secure_password
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[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 }
before_create :create_remember_token
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.digest(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.digest(User.new_remember_token)
end
end
Your User.rb model is out of sync with the one MHartl uses at that point in the tutorial. Specifically, notice that he has an explicit validates :password_confirmation, presence: true in addition to the validates :password, length: { minimum: 6 }. When you call #user.update_attributes, it hits these validators and, in his case, both fail, whereas in your User.rb model there is not the presence validator.
When you have the password field filled in, you're hitting validators defined in has_secure_password rather than in your model, which is why they appear then.
Make sure you include the password and password_confirmation in your allowed parameters in you controller:
private
def user_params
params.required(:user).permit(:name, :email, password,:password_confirmation)
end
EDIT:
As the other had already pointed out you miss the validation of password_confirmation
validates :password_confirmation, presence: true

Rails associated model is not updating in database

I'm trying to update my associated model, but it's not updating to the database and i'm not sure what to try next.
Model
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation,
:remember_me, :username, :login, :first_name,
:last_name, :home_phone, :cell_phone,
:work_phone, :birthday, :home_address,
:work_address, :position, :company, :user_details
has_one :user_details, :dependent => :destroy
accepts_nested_attributes_for :user_details
end
class UserDetails < ActiveRecord::Base
belongs_to :user
attr_accessible :home_phone, :position
end
Controller
# PUT /contacts/1/edit
# actually updates the users data
def update_user
#userProfile = User.find(params[:id])
respond_to do |format|
if #userProfile.update_attributes(params[:user])
format.html {
flash[:success] = "Information updated successfully"
render :edit
}
else
format.html {
flash[:error] = resource.errors.full_messages
render :edit
}
end
end
end
View
<%= form_for(#userProfile, :url => {:controller => "my_devise/contacts", :action => "update_user"}, :html => {:class => "form grid_6"}, :method => :put ) do |f| %>
<%= f.label :username, "Username" %>
<%= f.text_field :username, :required => "required" %>
<%= f.fields_for :user_details do |d| %>
<%= d.label :home_phone, "Home Phone" %>
<%= d.text_field :home_phone %>
<% end %>
<% end %>
<% end %>
Your attr_accessible should accept user_details_attributes, not just user_details.

How to get optional fields with form_for using rails?

I'm using Rails 3.2 and I'm trying to build a form to let a user update its data. However, if the user doesn't want to change its password it can do it by letting the fields blank.
Here is my code for the form :
<%= form_for(#user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :new_password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Save changes" %>
<% end %>
And here is my method update in the users controller:
def update
if #user.update_attributes(params[:user])
sign_in #user
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
When I'm leaving the password's fields blank, I always get flash messages for incorrect password.
Thank you
---UPDATE---
Here is my user model:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :team_id, :updating_password
before_save { |user| user.email = email.downcase }
before_save :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}
validates :password, presence: should_validate_password? , length: { minimum: 6 }
validates :password_confirmation, presence: should_validate_password?
def should_validate_password?
updating_password || new_record?
end
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
I think there is a really good answer to this question here: In Rails 3, how can I skip validation of the password field when I'm not attempting to update the password?
I would repeat it, but the given answer is pretty good. Also points to a railscast on the subject.

Resources