【问题标题】:Carrierwave does not create upload folderCarrierwave 不创建上传文件夹
【发布时间】:2015-10-30 13:46:51
【问题描述】:

我的主要问题是,通过carrierwave 上传文件时并没有真正上传。

我的控制台输出:

#<OptionPic id: 4, image_url: "game_of_thrones___tyrion_lannister_by_stanbos-d79k...", created_at: "2015-08-07 06:08:01", updated_at: "2015-08-07 06:08:01", option_id: 12>]>

对图像的调用如下

-@product.options.each do |option|
          -option.option_pics.each do |op|
            =image_tag op.image_url.to_s

如果我检查网页上的元素,这就是我得到的:

&lt;img src="/images/game_of_thrones___tyrion_lannister_by_stanbos-d79k0u9_modified.jpg" alt="Game of thrones tyrion lannister by stanbos d79k0u9 modified"&gt;

但是上传器上的设置如下:

class ProductImageUploader < CarrierWave::Uploader::Base

# Include RMagick or MiniMagick support:
include CarrierWave::RMagick
# include CarrierWave::MiniMagick

# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog

# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be    mounted:
def store_dir
   "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

不用说,我既没有在 assets/images 文件夹中创建图像,也没有创建 public/uploads 文件夹。

这在我的其他项目中完美运行(public/uploads 文件夹使用与上述相同的语法创建),其中图像存储为单独的模型。在我当前的项目中,我希望它们作为产品类的子选项。

结构如下:

模型 - 产品、选项、选项图片(ture)

一个产品可以有很多选项,而一个选项又可以有很多图片。例如 - 产品是一件 T 恤。选项有:材质和颜色。对于每种颜色,我想要一张不同的衬衫图片。

这就是我的 ProductsController 中包含所有内容的原因:

  Class ProductsController < ApplicationController

  before_action :find_product, only: [:show]

  def show
  end

  def index
    @products = Product.all
  end

  def new
    @product = Product.new
    @option = @product.options.new
    @option_pic = OptionPic.new
  end

  def edit
  end

  def create
    @product = Product.create(product_params)
    @option = @product.options.create(option_params)
    @option.product_id = @product.id
    @option.save

    @option_pic = @option.option_pics.create(pic_params)
    @option_pic.option_id = @option.id

    flash[:success] = "Product successfully created!"
    redirect_to products_path
  end

  private

    def product_params
        params.require(:product).permit(:title, :description, :advertising_text, :fancy_quote)
    end

    def option_params
      params.require(:option).permit(:size, :weight, :price, :material, :product_id)
    end

    def pic_params
      params.require(:option_pic).permit(:image_url, :option_id)
    end

    def find_product
        @product = Product.find(params[:id])
    end
end

我的 optionpic(ture) 模型:

class OptionPic < ActiveRecord::Base
    mount_uploader :product_image, ProductImageUploader
    belongs_to :option
end

我认为我只是犯了一些愚蠢的新手错误,但经过数小时的搜索后,我就是无法弄清楚出了什么问题。

编辑

我想出了两件事 - 我使用 image_url 而不是 picture_image 并忘记将 option_picture 值实际保存在控制器中,即@option_pic.save

现在上传时怎么没有数据传输:

SQL (0.3ms)  INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["product_image", nil], ["option_id", 18], ["created_at", "2015-08-07 08:03:28.559319"], ["updated_at", "2015-08-07 08:03:28.559319"]] 

我将每个值从 :image_url 更新为 :product_image(在视图中,在 pic_params 等中)

编辑 2

根据要求,我的上传表单:

%h1 Create new product

=form_for @product, url: products_path do |f|
    %p
        =f.label :title
        =f.text_field :title
        %br
        =f.label :description
        =f.text_area :description
        %br
        =f.label :advertising_text
        =f.text_area :advertising_text
        %br
        =f.label :fancy_quote
        =f.text_area :fancy_quote

    %p
        = fields_for @option do |o|
            =o.label :price
            =o.text_field :price
            %br
            =o.label :size
            =o.text_field :size
            %br
            =o.label :weight
            =o.text_field :weight
            %br
            =o.label :material
            =o.text_field :material
    %p
        = fields_for @option_pic, html: { multipart: true } do |op|
            = op.label 'Upload image'
            = op.file_field :product_image
    =f.submit

编辑 3

根据要求,我的日志参数

Started POST "/products" for ::1 at 2015-08-07 12:25:31 +0300
Processing by ProductsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"DOeZMvYpdoVmZRpsGmg2Gr9LIc9RYaS1KT1vdfhXI2BJaV3pPZZbZN8PJnvwQAig8wLPpIUORuf7Kjcw3BE6Zg==", "product"=>{"title"=>"fafa", "description"=>"", "advertising_text"=>"", "fancy_quote"=>""}, "option"=>{"price"=>"", "size"=>"", "weight"=>"", "material"=>""}, "option_pic"=>{"product_image"=>"level-3-on-rails-for-zombies-2-0eaaf0109f83459c5aedef30bdf8bd96.png"}, "commit"=>"Create Product"}
   (0.1ms)  BEGIN
  SQL (0.3ms)  INSERT INTO "products" ("title", "description", "advertising_text", "fancy_quote", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["title", "fafa"], ["description", ""], ["advertising_text", ""], ["fancy_quote", ""], ["created_at", "2015-08-07 09:25:31.365739"], ["updated_at", "2015-08-07 09:25:31.365739"]]
   (0.3ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO "options" ("size", "material", "product_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["size", ""], ["material", ""], ["product_id", 29], ["created_at", "2015-08-07 09:25:31.369112"], ["updated_at", "2015-08-07 09:25:31.369112"]]
   (0.3ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.3ms)  INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["product_image", nil], ["option_id", 21], ["created_at", "2015-08-07 09:25:31.372492"], ["updated_at", "2015-08-07 09:25:31.372492"]]
   (0.3ms)  COMMIT
Redirected to http://localhost:3000/products
Completed 302 Found in 10ms (ActiveRecord: 2.1ms)

【问题讨论】:

  • 显示上传表单的代码 (ERB)。
  • 显示您的请求真正收到的参数 - 复制来自log/development.log 的行。嵌套参数处理似乎有错误。
  • 也添加了它们(图片网址似乎在参数哈希中)
  • 是的,我是对的。为您添加了答案。

标签: ruby-on-rails file-upload carrierwave


【解决方案1】:

您没有正确访问您的params 值。以下将解决此问题:

def pic_params
  params.require(:option_pic).require(:product_image)
end

此外,您必须在构建 OptionPic 时使其属于您的 Option:

def new
  @product = Product.new
  @option = @product.options.new
  @option_pic = @option.option_pics.new
end

【讨论】:

  • 我不应该也嵌套需求吗?类似的东西:edgeapi.rubyonrails.org/classes/ActionController/… 因为现在我遇到了这个错误:ActionController::ParameterMissing at /products param is missing or the value is empty: option in def option_params params.require(:product).require(:option).permit(:size, :weight, :price, :material, :product_id) end
  • @mohnstrudel 对不起,我对嵌套哈希的看法是错误的。您应该将image_url 更改为product_image,但我们还没有解决这个问题。您的客户似乎没有发送文件。你在页面上有一些拦截上传的javascript吗?比如上传进度报告插件什么的?
  • 是的,我已经将所有 image_url 重命名为 product_image。而且我确实使用了引导模板,但是我尝试在完全禁用 javascript 的情况下提交表单,但仍然没有结果。我记得当我有 image_url 而不是 product_image 时,我的应用程序至少会保存 url,例如/images/game_of_thrones___tyrion_lannister_by_stanbos-d79k0u9_modified.jpg
  • @mohnstrudel 用另一个修复更新了我的答案。这可能是最后一个,也许我们会发现更多。
  • 这太奇怪了——起初我按照你的建议改变了我的代码。我的上传没有任何反应。然后我在我的产品表中添加了一个头像列(只是为了检查最标准的上传是否有效),在“新”页面上创建了一个头像上传器和两个文件字段 - 一个用于 product.avatar,旧一个用于 product_pic。现在两个文件都上传了!
【解决方案2】:

如果有人遇到同样的问题,我会发布我的解决方案 - 我决定使用嵌套属性重新创建这个系统,现在一切正常!

所以这里有我的 3 个模型:

class Product < ActiveRecord::Base

    belongs_to  :category 
    belongs_to  :subcategory
    has_many    :options

    has_and_belongs_to_many :product_sizes

    accepts_nested_attributes_for :options

end

选项类,它是产品的子类

class Option < ActiveRecord::Base
    belongs_to  :product
    has_many    :option_pics

    accepts_nested_attributes_for :option_pics
end

最后是 option_pic,一个选项的子节点

class OptionPic < ActiveRecord::Base
    mount_uploader :product_image, ProductImageUploader
    belongs_to :option
end

在产品控制器中,我的新操作和创建操作如下所示:

  def new
    @product = Product.new
    option = @product.options.build
    option_pic = option.option_pics.build
  end

  def edit
  end

  def create
    @product = Product.new(product_params)

    if @product.save!
      flash[:success] = "Product successfully created!"
      redirect_to products_path
    end
  end

  private

    def product_params
        params.require(:product).permit(
        :title, :description, :advertising_text, :fancy_quote, :category_id, 
        options_attributes: [:size, :weight, :price, :material, :product_id, 
          option_pics_attributes: [:product_image, :option_id]])
end

def find_product
    @product = Product.find(params[:id])
end

字符串参数是双重嵌套的,这很重要。 form_for 助手的结构也很重要。我没有重构它,所以现在它是一个大列表。那里的结构非常重要,我将 option_pic 的字段用于“f”变量的级别,这很关键,没有上传任何图像。

=form_for @product, url: products_path do |f|
    %p
        =f.label :title
        =f.text_field :title
        %br
        =f.label :description
        =f.text_area :description
        %br
        =f.label :advertising_text
        =f.text_area :advertising_text
        %br
        =f.label :fancy_quote
        =f.text_area :fancy_quote
        %br
        =f.label :category_id
        =f.collection_select :category_id, Category.all, :id, :title, { prompt: 'Please select category' }
        %br
        =f.label 'Product Size'
        =f.collection_check_boxes(:product_size_ids, ProductSize.all, :id, :size)

    %p
        = f.fields_for :options do |builder|
            =builder.label :price
            =builder.text_field :price
            %br
            =builder.label :size
            =builder.text_field :size
            %br
            =builder.label :weight
            =builder.text_field :weight
            %br
            =builder.label :material
            =builder.text_field :material
            %br
            =builder.fields_for :option_pics do |op|
                = op.label 'Upload image'
                = op.file_field :product_image
    =f.submit

瞧,一个精彩的提交:

(0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "products" ("title", "description", "advertising_text", "fancy_quote", "category_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["title", "builder"], ["description", ""], ["advertising_text", ""], ["fancy_quote", ""], ["category_id", 1], ["created_at", "2015-08-11 11:34:11.618298"], ["updated_at", "2015-08-11 11:34:11.618298"]]
  SQL (0.2ms)  INSERT INTO "options" ("size", "price", "material", "product_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["size", ""], ["price", 555], ["material", ""], ["product_id", 82], ["created_at", "2015-08-11 11:34:11.619678"], ["updated_at", "2015-08-11 11:34:11.619678"]]
  SQL (0.5ms)  INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["product_image", "b3c839_bd43d840e031469495137fa74e31faf4.jpg_srz_428_428_75_22_0.5_1.2_75_jpg_srz"], ["option_id", 66], ["created_at", "2015-08-11 11:34:11.620837"], ["updated_at", "2015-08-11 11:34:11.620837"]]
   (0.3ms)  COMMIT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 2013-11-20
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 2012-04-22
    相关资源
    最近更新 更多