"没有将nil隐式转换为String"载波多个图像上传的错误

时间:2015-10-28 21:08:38

标签: ruby-on-rails devise carrierwave

这几天困扰着我。我试过不同的方法。所以我会选择最简单的形式,这应该是有效的,但不是。

我有两个型号。 InstituteVirtualTour

class Institute < ActiveRecord::Base
  mount_uploader :virtual_images, VirtualPicUploader

  has_many :virtual_tours, dependent: :destroy
  accepts_nested_attributes_for :virtual_tours,allow_destroy: true
end


class VirtualTour < ActiveRecord::Base
  belongs_to :institute
  mount_uploader :image, VirtualPicUploader
end

我对devise学院很有兴趣。这个更简单的版本没有考虑强参数,所以我会保持这样。

  def account_update
      default_params.permit!
  end

在编辑时会发生此上传,这就是使用account_update的原因。

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put ,  multipart: true }) do |f| %>
  <%= f.fields_for :virtual_tours do |ff| %>
   <%= ff.file_field :image, multiple: true %>
   <%= ff.hidden_field :institute_id, value: f.object.id %>
  <% end %>
<% end %>

我提交时在浏览器中收到此错误。

   no implicit conversion of nil into String

   def cache_path
      File.expand_path(File.join(cache_dir, cache_name), root)
   end

在日志中, 在91ms内完成500内部服务器错误(ActiveRecord:1.8ms)

TypeError (no implicit conversion of nil into String):
  carrierwave (0.10.0) lib/carrierwave/uploader/cache.rb:159:in `join'
  carrierwave (0.10.0) lib/carrierwave/uploader/cache.rb:159:in `cache_path'
  carrierwave (0.10.0) lib/carrierwave/uploader/cache.rb:131:in `block in cache!'
  carrierwave (0.10.0) lib/carrierwave/uploader/callbacks.rb:17:in `with_callbacks'
  carrierwave (0.10.0) lib/carrierwave/uploader/cache.rb:122:in `cache!'
  carrierwave (0.10.0) lib/carrierwave/mount.rb:329:in `cache'
  carrierwave (0.10.0) lib/carrierwave/mount.rb:163:in `image='
  carrierwave (0.10.0) lib/carrierwave/orm/activerecord.rb:39:in `image='
  activerecord (4.2.4) lib/active_record/attribute_assignment.rb:54:in `public_send'
  activerecord (4.2.4) lib/active_record/attribute_assignment.rb:54:in `_assign_attribute'
  activerecord (4.2.4) lib/active_record/attribute_assignment.rb:41:in `block in assign_attributes'
  actionpack (4.2.4) lib/action_controller/metal/strong_parameters.rb:185:in `each_pair'
  actionpack (4.2.4) lib/action_controller/metal/strong_parameters.rb:185:in `each_pair'
  activerecord (4.2.4) lib/active_record/attribute_assignment.rb:35:in `assign_attributes'
  activerecord (4.2.4) lib/active_record/nested_attributes.rb:513:in `assign_to_or_mark_for_destruction'
  activerecord (4.2.4) lib/active_record/nested_attributes.rb:479:in `block in assign_nested_attributes_for_collection_association'
  activerecord (4.2.4) lib/active_record/nested_attributes.rb:460:in `each'

过去两天一直在研究这个问题。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:12)

我遇到了同样的问题。我用它来修复它 mount_uploaders不是mount_uploader

答案 1 :(得分:1)

我已将文档here包含在内以供参考。

入门可以帮助我们开始。我假设您尝试同时上传多张图片时发生错误?

尽管如此,这是我在使用载波实现文件上传时所采取的步骤。

CarrierWave的documentation引导我们完成将其与我们的应用程序集成的过程,但这里列出了基本步骤:

  1. 将gem添加为依赖项。
  2. 创建一个上传器,用于定义文件的存储位置。
  3. 向我们的模型添加属性以存储文件位置。
  4. 将上传器与模型集成。 假设我们想要将配置文件照片添加到具有User模型的应用程序,我们可以先将gem添加到我们的Gemfile中来安装gem:

    gem "carrierwave" 要么 gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'用于多张图片上传。

  5. 使用bundle命令下载并安装gem:

    $ bundle
    Installing carrierwave ...
    ....
    

    现在我们需要一个可以存储个人资料照片的上传器。我们可以使用CarrierWave附带的生成器创建一个:

    $ rails generate uploader ProfilePhoto
    

    这将在app / uploaders / profile_photo_uploader.rb中创建一个新文件。如果我们查看该文件,我们会看到许多配置上传器的选项,但现在我们关注文件的存储位置:

    class ProfilePhotoUploader < CarrierWave::Uploader::Base
      storage :file
    
      def store_dir
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
      end
    end
    

    storage :file选项指定文件本地存储在Web服务器(即我们的笔记本电脑)上。这对于开发来说很好,但是当我们部署到生产服务器时,我们希望稍后更改它。

    store_dir方法指定我们可以找到上传文件的目录。默认情况下,路径将从公共文件夹开始,以便可以访问上载的文件。如果我们在U​​ser模型上安装此上传器,则完整路径为/public/uploads/user/profile_photo/#{user.id}/file_name。每个用户都有自己的目录,以防止其他用户覆盖同名文件。

    现在我们有了上传器,我们需要在users表中添加一列,以便我们可以存储文件的位置。我们创建一个迁移来添加profile_photo列:

    $ rails generate migration add_profile_photo_to_users

    我们可以修改我们的迁移文件以包含以下内容:

    class AddProfilePhotoToUsers < ActiveRecord::Migration
      def change
        add_column :users, :profile_photo, :string
      end
    end
    

    运行此迁移后,我们现在可以存储与每个用户关联的个人资料照片。

    最后一步是通过ProfilePhotoUploader列附加我们使用User模型创建的profile_photo。我们可以将以下行添加到User模型中:

    class User < ActiveRecord::Base
      mount_uploader :profile_photo, ProfilePhotoUploader
    end
    

    现在我们可以在profile_photo模型上调用User方法,它会返回上传文件的详细信息。

    要完成个人资料照片上传功能,我们还需要在用户注册表单上添加一个位置,以允许用户在其计算机上选择图像。使用form_for,我们可以添加以下内容:

    <%= f.file_field :profile_photo %>

    这些方法会将<input type="file">元素添加到表单中,以便它向用户显示一个用于选择文件的对话框。

    最后一步是确保个人资料照片可以通过用户控制器上的强参数。如果我们使用Devise,我们可以使用我们可以在app/controllers/application_controller.rb中定义的前置过滤器为注册过程注入新属性:

    class ApplicationController < ActionController::Base
      before_action :configure_permitted_parameters, if: :devise_controller?
    
      protected
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.for(:sign_up) << :profile_photo
      end
    end
    

    此时,用户应该能够在创建或更新注册时选择个人资料照片,并且图像将与用户相关联。

    注意:请注意,carrierwave将使用rails使用的命名约定。如果您将文件命名为Uploader类AvatarUploader,它将查找以avatar avatar_uploader.rb命名的文件(奇异的模型)。

    更新:对于多个图片上传者,请确保您的模型中有mount_uploaders而不是单数形式。

答案 2 :(得分:0)

更改<%= ff.file_field :image, multiple: true %>

<%= ff.file_field :image %>

multiple: true不需要添加字段。