关于多图上传的seed文档的思考

Published on:

按YY老师这个教程:實作carrierwave上傳多個圖片
完成多图上传功能之后,rails c后台Photo.detele_all之后,local3000就正常了,后台也可以正常上传多张图片。

YY老师提示先在后台上传几张图片,然后rails c看看Photo.all,领悟其中的关系。

当初我试过rails c,可惜愚笨,并没有领悟出解决方法。

然后我就开始瞎尝试修改seed文件了(以单个产品来举例)。
当时是这么写的:

seed.rb
products =[

                    {
                    title:"部署到Heroku,图片不显示?",
          description: "此经验由@panxiubin助教提供。初次使用aws服务的同学,在将专案部署到heroku之后,常常会遇到图片无法正常显示的问题,此经验可以有效的解决这个问题,有图有真相,灰常容易理解。",
                    body: "具体请手机扫描下方二维码跳转logdown链接。",
                    category: "heroku",
          image_path: ["#{Rails.root}/app/assets/images/heroku1.jpg",
                                             "#{Rails.root}/app/assets/images/herokuma1.png"]
                 },
]

p1 = Product.create([title:products[0][:title],description:products[0][:description],body:products[0][:body],category:products[0][:category],quantity:rand(3..9) * 100 ,price:rand(1..5),image:(products[0][:image_path].map{|file|open(file)})])

当时是根据这个 ruby doc ,用map这个method来open我在seed文档中写好的images array。

运行的时候报错了:

提示
TypeError: no implicit conversion of nil into String

当时我怀疑,是avator的属性不符合,所以修改

class CreatePhotos < ActiveRecord::Migration[5.0]
  def change
    create_table :photos do |t|
      t.integer :product_id
      t.Array :avatar

      t.timestamps
    end
  end
end

把string改成了Array,一开始用array,最后提示Array

运行$ rake db migrate
提示:

提示
ActiveRecord::NoEnvironmentInSchemaError:

Environment data not found in the schema. To resolve this issue, run:

        bin/rails db:environment:set RAILS_ENV=development

$ bin/rails db:environment:set RAILS_ENV=development

提示
private method `Array' called for #<ActiveRecord::ConnectionAdapters::TableDefinition:0x007fdb782bf100>

这条路明显不奏效,因为当初我还不太理解YY老师教程中的photo和avatar。

接着,我考虑修改input标签image
改成photo如下:

运行之后报错:

提示
rake aborted!
ActiveRecord::AssociationTypeMismatch: Photo(#70197414385420) expected, got File(#70197415570760)

改成avatar之后报错:

提示
rake aborted!
ActiveModel::UnknownAttributeError: unknown attribute 'avatar' for Product.

后来我再次尝试金手指,看看product_id 和photo之间的关系:

看的出来,就是一个product_id对应多个Photo id。

但我不太明白如何才能把他们的关系像这样对应起来。
当初我能想到的是,用一个循环语句来尝试把关系对应起来,先把product和photo建立起来,产生product_id和Photo id,然后:

i = Photo id

for i in 1..2 do
    product_id = 1
do

现在来看,真是好愚蠢啊,哈哈哈哈哈。

后来,经过YY老师明说,才彻底明白。

1.首先Photo是一个model
作为一个被定义了的model,它是可以自己create的。
因此是可以执行这个命令的:
Photo.create!( )

2.create vs create!
从这个edgeguidesguides,我们可以看到其中的区别


That's say,save! will raise an error if not successful.
however,save will return true or false.

好,现在我们回头来看看前面报错的原因:

报错1:no implicit conversion of nil into String

首先,如果一定要用image,add_image_to_product.rb的这个设定只支持单图

class AddImageToProduct < ActiveRecord::Migration[5.0]
  def change
    add_column :products, :image, :string
  end
end

所以,如果硬要传多张图上去就会这样报错,如果一定要用image,解决方法是根据 carrierwave 改相关的设定
至少包括三个方面:

  • add images column as sting also
  • make image input a multiple files input
    mount_uploaders :images, ProductImageUploader
    
  • allow nested params as array in params
    params.require(:product).permit(:title, :description, :images => [])
    

报错2:ActiveModel::UnknownAttributeError: unknown attribute 'avatar' for Product.

很简单,avatar并不是在model product下定义的Uploader,因此才会出现这样的报错。

所以呢,avarar标签只能在Photo.create!( )这里来使用。

下面是正确步骤:

1.create product to create product_id

seed.rb
p1 = Product.create([title:products[0][:title],description:products[0][:description],body:products[0][:body],category:products[0][:category],quantity:rand(3..9) * 100 ,price:rand(1..5)])

2.connect product_id to photo id when creating photo

seed.rb
Photo.create!(product_id:1,avatar: open(photos[0]))
Photo.create!(product_id:1,avatar: open(photos[1]))

通过这两部,就成功为第一个商品增加了两个图片。

Comments

comments powered by Disqus