首页 > 解决方案 > Rails 5.2 ActiveStorage - 如何确定图像是否新上传

问题描述

导轨版本 - 5.2.3

有没有办法确定图像(或任何文件)是否是新附件?如果某个文件不是新附件,我希望我的模型中的一个方法简单地返回,但如果它是新附加的,则将该文件的 URL/路径分配给模型的属性。

我试过这个image.new_record?电话,但它总是返回false。当然,只要我已经在数据库中上传了文件,它image.attached?就会一直返回。true

models/user.rb(仅显示相关行)

class User < ApplicationRecord
  include Rails.application.routes.url_helpers

  before_update :assign_profile_pic, :assign_cover_pic

  has_many_attached :profile_images
  has_many_attached :cover_images 

  private

  def assign_profile_pic
    return unless profile_images.attached?

    self.profile_pic = rails_blob_path(profile_images.last, only_path: true)
  end

  def assign_cover_pic
    return unless cover_images.attached?

    self.cover_pic = rails_blob_path(cover_images.last, only_path: true)
  end

end

users_controller.rb(仅显示更新操作和 user_params):

def update
    user = find_user
    return unless user

    authorize user
    if user.update(user_params)
      render :show, locals: { user: user }, status: :accepted
    else
      process_error(user, 'Cannot update user')
    end
end

private

def user_params
    params.require(:user).permit(
      :email,
      :username,
      :password,
      :password_confirmation,
      :first_name,
      :last_name,
      :middle_name,
      :bio,
      :birthday,
      :gender,
      profile_images: [],
      cover_images: []
    )
  end

我需要发生的是,如果我不上传新图像(在update控制器的操作中),assign_profile_pic 和/或assign_cover_pic 将简单地返回。例如,我只想将 profile_pic 重新分配给之前已经上传的图像(可能是也可能不是profile_images.last)。但是,据我研究,没有办法确定特定文件是否是新附件。

我有一个解决方法,它将逻辑放入update操作中:

def update
    user = find_user
    return unless user

    authorize user
    if user.update(user_params)
      # i can check here whether user_params[:profile_images] is nil or not

      user.assign_profile_pic unless user_params[:profile_images].nil?
      user.assign_cover_pic unless user_params[:cover_images].nil?

      render :show, locals: { user: user }, status: :accepted
    else
      process_error(user, 'Cannot update user')
    end
  end

这也意味着assign_profile_pic并将assign_cover_pic成为模型中的公共方法User(并在每个方法中包含该行save)。

不过,我对这种解决方法有点不舒服。这是因为它在下面添加了另一个对数据库的调用user.update,然后它增加了控制器的复杂性(它没有应该的那么薄)。

最好的方法是什么?

标签: ruby-on-rails-5rails-apirails-activestorage

解决方案


推荐阅读