Rails 6: 如何在模型之外对 ActiveStorage 项运行验证?



我有一个模型Profile它有一个附件image

class Profile < ApplicationRecord
belongs_to :user, dependent: :destroy
has_one_attached :image
validates :image,
content_type: [:gif, :png, :jpg, :jpeg],
size: { less_than: 2.megabytes , message: 'must be less than 2MB in size' }
after_initialize :set_default_image
has_many :gallery_items, dependent: :destroy
accepts_nested_attributes_for :gallery_items, allow_destroy: true
validates :name, :short_description, :slug, presence: true
#...

除了映像验证(我使用的是活动存储验证 gem(之外,Profile还验证是否存在nameshort_descriptionslug

自从实施以来,我有一个新的要求。我现在希望允许用户将图像与其他属性分开提交。

我不想更改基础模型。因此,我想引入一个单独的控制器和类来处理单独提交图像的表单。

我尝试了两种方法。

首先,我有一个简单的类来处理这个问题:

class ProfileImageFormSubmission
def initialize(record, params)
@params = params
@record = record
end
def save
record.update_attribute(:image, image_param)
end
private
attr_accessor :params, :record
def image_param
params.fetch(record_param).require(:image)
end
def record_param
record.class.name.underscore.to_sym
end
end

它将在我的控制器中调用,如下所示:

class ProfileImagesController < ApplicationController
before_action :require_login
def update
@profile = Profile.find_by(user_id: current_user.id)
if ProfileImageFormSubmission.new(@profile, params).save
#...

问题是,图像未经验证,因此无论如何都会附加到配置文件。(我之所以使用#update_attribute,是因为我想跳过对其他属性的验证 - 当字段未呈现给用户时,显示名称列的错误是没有意义的。

我还尝试通过在模型外部运行验证来解决问题。但在这里,我正在努力理解如何将ActiveStorage与一个普通的旧 Ruby 对象集成。

class ProfileImageFormSubmission
include ActiveModel::Model
include ActiveStorage
include ActiveStorageValidations
attr_accessor :record, :params
has_one_attached :image
validates :image,
content_type: [:gif, :png, :jpg, :jpeg],
size: { less_than: 2.megabytes , message: 'must be less than 2MB in size' }
def initialize(record, params)
@params = params
@record = record
end
def save
binding.pry
record.update_attribute(:image, image_param)
if record.invalid?
record.restore_attributes
return false
end
end
# This model is not backed by a table
def persisted?
false
end
private
def image_param
params.fetch(record_name).require(:image)
end
def object_name
record.class.name.underscore.to_sym
end
end

我什至无法实例化上述类,因为它失败并出现以下错误:

NoMethodError (undefined method `has_one_attached' for ProfileImageFormSubmission:Class):

单独验证活动存储项的最佳方法是什么?

是否可以在不触发其他验证错误的情况下对单个列运行验证?

是否可以在ApplicationRecord模型之外使用活动存储项?

你不能只用一个模型来做到这一点。需要使用活动存储验证创建第二个"映像"或"附件"类,然后才能先创建映像。

即使可能将所有内容都保留在一个模型中,跳过验证也会导致数据不一致。将其分开将确保数据库中的每条记录都有效,并且您不会遇到意外状态(例如没有名称的配置文件,即使您正在"验证"它的存在(。

所以它看起来像这样:

class Image < ApplicationRecord
(...)
has_one_attached :file
validates :file,
content_type: [:gif, :png, :jpg, :jpeg],
size: { less_than: 2.megabytes , message: 'must be less than 2MB in size' }
(...)
end
class Profile < ApplicationRecord
(...)
has_one :image # or belongs to
(...)
end

试试这个

class ProfileImageFormSubmission
def initialize(record, params)
@params = params
@record = record
end
def save
record.assign_attributes(image: image_param)
record.valid?
record.errors.to_hash.except(:image).each { |k,_| record.errors.delete(k) } # removing errors for other attributes
return false if record.errors.any?
record.save(validate: false)
end
...

如果Profile对于User不是强制性的。然后,您可能希望将图像移动到类User

我遇到了同样的错误,我不得不为模型建立一座小桥。

class ApplicantForm
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :applicant, :first_name, :last_name, :photo
validates :first_name, :last_name, :photo, presence: true
validate :format_and_size_of_photo
def save
if valid?
applicant.update(first_name: first_name, last_name: last_name)
end
end
def format_and_size_of_photo
applicant.validate

errors.add(:photo, applicant.errors[:photo]) if applicant.errors[:photo].present?
end
end

在模型中,我有ActiveStorageValidations

相关内容

  • 没有找到相关文章

最新更新