[英]Updating only some attributes in a rails model
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). 我正在寻找一种通用的解决方案,该解决方案可以让我将来扩展以仅更新特定的字段子集(将2FA添加到安全性部分将要求用户更改其密码以按原样更新其2FA密钥)。
The only outside gems I am using are the Have I Been Pwned gem and an updated email_check gem . 我正在使用的唯一外部宝石是“ 我曾经拥有”宝石和更新的email_check宝石 。
My current code is: 我当前的代码是:
routes.rb 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 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 和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. 如果仅在输入密码后才想验证密码字段,请按以下条件使用proc对象。 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? }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.