ruby-on-rails - 即使设置了错误,Rails Record 也会被保存
问题描述
这是我的凭证模型:
class Credential < ApplicationRecord
validate :password_or_certificate
enum credential_type: { windows: 1, linux: 2 }
def password_or_certificate
unless user_pass.blank? ^ cert_file_path.blank?
errors.add(:base, "Please provide a password or a certificate, not both.")
end
end
end
我正在检查控制器中的证书并在控制器中设置错误,如下所示:
def create
attachment = params[:credential][:cert_file_path]
cert_file_path = Rails.root.join('private', 'certificates', attachment.original_filename) if attachment.present?
@credential = Credential.new(credential_params)
@credential.cert_file_path = cert_file_path
if @credential.valid? && cert_file_path.present?
cert_error_msg = 'Certificate is not valid'
fm = FileMagic.new(FileMagic::MAGIC_MIME)
file_path = attachment.path
if fm.file(file_path) =~ /^text\//
puts first_line = File.open(attachment.path) { |f| f.readline }
if first_line.include? '-----BEGIN RSA PRIVATE KEY-----'
File.open(cert_file_path, 'w') { |f| f.write(attachment.read) }
else
@credential.errors.add(:cert_file_path, cert_error_msg)
end
else
@credential.errors.add(:cert_file_path, cert_error_msg)
end
end
respond_to do |format|
if @credential.save
format.html { redirect_to credentials_url, notice: 'Credential was successfully mapped.' }
format.js
format.json { render :show, status: :created, location: @credential }
else
format.html { render :new }
format.js
format.json { render json: @credential.errors, status: :unprocessable_entity }
end
end
end
即使设置了错误,记录也会被保存。
#<ActiveModel::Errors:0x0000557781babde8 @base=#<Credential id: nil, alias: "My new credential", user_name: "raj", encrypted_user_pass: "", encrypted_user_pass_iv: "VrT0xsxYtf//cwVx\n", credential_type: "linux", created_at: nil, updated_at: nil, cert_file_path: "/home/rmishra/awsapp/private/certificates/Ruby Enc...", passphrase: "">, @messages={:cert_file_path=>["Certificate is not valid"]}, @details={:cert_file_path=>[{:error=>"Certificate is not valid"}]}>
我知道我可以检查@credential.errors.blank?
然后保存它,你们能帮我把所有这些逻辑放在我的模型中吗?
解决方案
您可以创建自定义验证方法以将该逻辑移动到您的模型中,并创建虚拟属性以获取对附件对象的访问权限
模型
class Credential < ApplicationRecord
validate :password_or_certificate
enum credential_type: { windows: 1, linux: 2 }
# create a virtual attribute to store attachment
attr_accessor :attachment
# Custom validation method on ActiveRecord object creation
validate :create_certificate, on: :create
def create_certificate
if cert_file_path.present?
cert_error_msg = 'Certificate is not valid'
fm = FileMagic.new(FileMagic::MAGIC_MIME)
file_path = attachment.path
if fm.file(file_path) =~ /^text\//
puts first_line = File.open(attachment.path) {|f| f.readline}
if first_line.include? '-----BEGIN RSA PRIVATE KEY-----'
File.open(cert_file_path, 'w') {|f| f.write(attachment.read)}
else
errors.add(:cert_file_path, cert_error_msg)
end
else
errors.add(:cert_file_path, cert_error_msg)
end
else
errors.add(:cert_file_path, cert_error_msg)
end
end
def password_or_certificate
unless user_pass.blank? ^ cert_file_path.blank?
errors.add(:base, "Please provide a password or a certificate, not both.")
end
end
end
控制器
def create
attachment = params[:credential][:cert_file_path]
cert_file_path = Rails.root.join('private', 'certificates', attachment.original_filename) if attachment.present?
@credential = Credential.new(credential_params)
@credential.cert_file_path = cert_file_path
@credential.attachment = attachment
respond_to do |format|
if @credential.save
format.html {redirect_to credentials_url, notice: 'Credential was successfully mapped.'}
format.js
format.json {render :show, status: :created, location: @credential}
else
format.html {render :new}
format.js
format.json {render json: @credential.errors, status: :unprocessable_entity}
end
end
end
推荐阅读
- javascript - 查找字符串中所有缺失的字母(字符串按字母顺序排列)
- typescript - 谷歌云构建,在 monorepo 中引用父文件夹
- javascript - 使用 foreach 循环创建数组并使用 webworker postMessage 将其传回
- pug - 如何使用 pug/jade 仅显示字符串的一部分?
- python - 请求库不会通过指定 url 中的 python 代码解码 unicode 字符
- icalendar - ical RRULE 例外日期
- reactjs - React 认为我的函数组件是一个对象(而不是函数)
- java - 无法使用 selenium BDD 框架运行登录测试
- reactjs - 如何避免在useEffect中didmount时调用清理函数?
- node.js - Firebase无密码登录电子邮件链接过期时间太短