无法使用 active_admin 和载波保存图像

Can't save image with active_admin and carrierwave

我有下一个模型:

文章:

class Article < ApplicationRecord
  validates :name, length: { maximum: 240 }, presence: true

  has_one :image,
          as: :imageable,
          class_name: 'CatalogImage',
          autosave: true,
          dependent: :destroy
  accepts_nested_attributes_for :image, allow_destroy: true
end    

目录图片:

class CatalogImage < ApplicationRecord
  belongs_to :imageable, polymorphic: true

  validates :file, presence: true
  mount_uploader :file, ImageUploader
end

活动管理表单:

form do |f|
  f.inputs do
    f.input :name
    f.input :content, as: :ckeditor
    f.input :position
    f.input :active, as: :radio
    f.input :place_on_home_page, as: :radio
    # f.input :image, as: :file

    # same with -> [:image, f.object.image || CatalogImage.new]
    f.inputs 'Image', for: [:image, f.object.build_image] do |fi|
      fi.input :file, as: :file, label: 'Image'
              #  hint: (f.template.image_tag(f.object.image&.url) rescue nil)
    end
  end
  f.actions
end

上传者(之前工作过,但它甚至没有触及 byebug):

class ImageUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    byebug
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

  def filename
    if original_filename
      original_filename.gsub! /\s*[^A-Za-z0-9\.\/]\s*/, '_'
      original_filename.strip
      original_filename.downcase
    end
  end
end

我用 byebug 检查了我的模型、图像和文件字段是否正确。但结果 - 我的表格没有任何错误,但它再次显示 new 表格.如果我没有 select 任何文件,它会保存文章。 (我也允许所有属性,因为它不允许所有必要的)。

    [4, 13] in /usr/src/app/app/admin/articles.rb
    4:   # permit_params :name, :content, :position, :active,
    5:   #               image_attributes: [%i[id file _destroy]]
    6:
    7:   before_create do |article|
    8:     byebug
=>  9:   end
    10:
    11:   controller do
    12:     def permitted_params
    13:       params.permit!
(byebug) article.image.file
    #<ImageUploader:0x0000556fe6020ed0 @model=#<CatalogImage id: nil, imageable_type: "Article", imageable_id: nil, name: nil, file: nil, file_content_type: nil, position: nil, info: nil, created_at: nil, updated_at: nil>, @mounted_as=:file, @cache_id="1517464302-1-0005-0263", @filename="soldati-house-interior-by-victor-vasilev-o.jpg", @original_filename="soldati-house-interior-by-victor-vasilev-o.jpg", @file=#<CarrierWave::SanitizedFile:0x0000556fe741bde0 @file="/usr/src/app/public/uploads/tmp/1517464302-1-0005-0263/soldati-house-interior-by-victor-vasilev-o.jpg", @original_filename="soldati-house-interior-by-victor-vasilev-o.jpg", @content_type="image/jpeg">, @cache_storage=#<CarrierWave::Storage::File:0x0000556fe741ac60 @uploader=#<ImageUploader:0x0000556fe6020ed0 ...>>, @versions={:thumb=>#<ImageUploader::Uploader46969554945920:0x0000556fe70613f8 @model=#<CatalogImage id: nil, imageable_type: "Article", imageable_id: nil, name: nil, file: nil, file_content_type: nil, position: nil, info: nil, created_at: nil, updated_at: nil>, @mounted_as=:file, @parent_version=#<ImageUploader:0x0000556fe6020ed0 ...>, @parent_cache_id="1517464302-1-0005-0263", @cache_id="1517464302-1-0005-0263", @filename="soldati-house-interior-by-victor-vasilev-o.jpg", @original_filename="soldati-house-interior-by-victor-vasilev-o.jpg", @file=#<CarrierWave::SanitizedFile:0x0000556fe6adb370 @file="/usr/src/app/public/uploads/tmp/1517464302-1-0005-0263/thumb_soldati-house-interior-by-victor-vasilev-o.jpg", @original_filename="soldati-house-interior-by-victor-vasilev-o.jpg", @content_type="image/jpeg">, @cache_storage=#<CarrierWave::Storage::File:0x0000556fe6ff8650 @uploader=#<ImageUploader::Uploader46969554945920:0x0000556fe70613f8 ...>>, @versions={}>}>
    (byebug) n

    [74, 83] in /usr/local/bundle/gems/activeadmin-1.2.1/lib/active_admin/callbacks.rb
    74:           end
    75:
    76:           # def run_create_callbacks
    77:           define_method "run_#{name}_callbacks" do |*args, &block|
    78:             self.class.send("before_#{name}_callbacks").each{ |cbk| run_callback(cbk, *args) }
 => 79:             value = block.try :call
    80:             self.class.send("after_#{name}_callbacks").each { |cbk| run_callback(cbk, *args) }
    81:             return value
    82:           end
    83:           send :private, "run_#{name}_callbacks"
(byebug) c
(0.6ms)  BEGIN
             (0.3ms)  ROLLBACK
             Rendering /usr/local/bundle/gems/activeadmin-1.2.1/app/views/active_admin/resource/new.html.arb

Rails 5.1.4 ActiveAdmin 1.2.1

更新:

如果我尝试使用另一个扩展文件,它会显示错误。

可以像 has_many 那样对待 has_one 关联。所以,这有效:

  f.object.build_image if f.object.image.nil?

  f.has_many :image, new_record: f.object.image.nil?, allow_destroy: true do |ff|
    ff.input :file, as: :file, hint: (ff.object&.file&.present? &&
                                      image_tag(ff.object&.file&.url(:thumb)))
    ff.input :file_cache, as: :hidden
  end

这里如果没有对象我也建立新的对象,如果我们已经有对象则不允许添加新对象。

Update 而且我必须向图像模型添加 optional 标志,因为在 rails 5 中默认需要此关联:

class CatalogImage < ApplicationRecord
  belongs_to :imageable, polymorphic: true, optional: true

此后有效。