I am trying to create an account management page in which you can update your display name, email, password, and other stuff. I want to allow the user to update only part of their information without the model rejecting the changes if unchanged info is invalid. I need to update only part of a model, specifically updating account details without having to enter a password and confirmation.
Using a single form requires the user to change their password when updating details. I tried splitting the account details into a "profile" and "security" form hopefully to not send an empty password when updating somebody's name, but the model rejects the change noting the password is missing. However, updating only the password with the two form setup seems to work just fine.
I am looking for a general solution that would let me expand to only update a specific subset of fields in the future (adding 2FA to the security section would require the user to change their password to update their 2FA key as is).
The only outside gems I am using are the Have I Been Pwned gem and an updated email_check gem .
My current code is:
routes.rb
Rails.application.routes.draw do
# ...
get '/account', to: 'account#index'
post '/account', to: 'account#update'
root 'application#home'
end
the account model
class Account < ApplicationRecord
self.primary_key = :id
before_validation do
self.id.to_s.downcase! # lowercase the id
self.email.to_s.downcase! # lowercase the email
end
validates :id,
presence: true,
length: { minimum: 5, maximum: 32 },
uniqueness: true,
format: { with: /\A[a-z0-9-]*\z/, message: 'Only lowercase alphabet, numbers and dash allowed.' }
validates :name,
presence: true,
length: { minimum: 2, maximum: 50 }
validates_email_strictness :email,
message: 'Something about that email doesn\'t look right... Make sure the spelling is right or try another?'
has_secure_password
validates :password,
presence: true,
not_pwned: true,
format: { with: /\d/ },
length: { minimum: 8 }
attr_accessor :password_confirmation
attr_accessor :remember_token
end
account_controller.rb
class AccountController < ApplicationController
def index
if logged_in?
@account = current_account
else
flash[:danger] = "You must be logged in to do that!"
redirect_to '/account/login'
end
end
def update
@account = current_account
# TODO security concerns or otherwise when receiving only profile, security, etc fields
if @account.update_attributes(account_params)
flash.now[:success] = 'Update success!'
else
flash.now[:danger] = 'Something went wrong!'
end
render 'index'
end
private def account_params
params.require(:account).permit(:id,:name,:email,:password,:password_confirmation)
end
end
and the account/index.html.erb
<% provide(:title,'Manage Account') %>
<h1>Manage Account</h1>
<%= render 'shared/error_messages' %>
<h3>Profile & Contact Info</h3>
<div>
<p>Account ID</p>
<input disabled value="<%= @account.id %>">
<form action="/account" method="post">
<input name="utf8" type="hidden" value="✓" />
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
<p>Name</p>
<input name="account[name]" value="<%= @account.name %>">
<p>Email</p>
<input name="account[email]" value="<%= @account.email %>" type="email">
<button type="submit">Submit</button>
</form>
</div>
<h3>Password & Security</h3>
<form action="/account" method="post">
<input name="utf8" type="hidden" value="✓" />
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
<p>New Password</p>
<input name="account[password]" type="password">
<p>Confirm New Password</p>
<input name="account[password_confirmation]" type="password">
<button type="submit">Submit</button>
</form>
If you want to validate password field only when it is entered then use proc object conditionally as below. This will allow other fields to update irrespective of the password field
validates :password,
presence: true,
not_pwned: true,
format: { with: /\d/ },
length: { minimum: 8 }, unless: Proc.new { |account| account.password.blank? }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.