Localhost 有效,但 Heroku 在使用 active_storage 和 Rails 5.2 上传照片时抛出 500

Localhost works, but Heroku throws 500 when uploading photo with active_storage and Rails 5.2

我正在尝试使用 ActiveStorage 和 Rails 5.2 进行基本的照片上传。它在 localhost 上完美运行,但是当我尝试在 Heroku 中创建新对象时 运行 出现 500 错误。不幸的是,Heroku 日志根本没有帮助:

2018-08-11T20:06:44.886851+00:00 app[web.1]: http://mab-staging.herokuapp.com/products/new -> /products
2018-08-11T20:06:44.886308+00:00 heroku[router]: at=info method=POST path="/products" host=mab-staging.herokuapp.com request_id=6557c78a-fbc1-4059-9904-c4b1122f8930 fwd="68.225.227.137" dyno=web.1 connect=0ms service=79ms status=302 bytes=1304 protocol=http
2018-08-11T20:06:45.143034+00:00 heroku[router]: at=info method=GET path="/products" host=mab-staging.herokuapp.com request_id=46ba7cc2-953a-4236-806c-44248a9625fe fwd="68.225.227.137" dyno=web.1 connect=1ms service=153ms status=500 bytes=1262 protocol=http
2018-08-11T20:06:45.143727+00:00 app[web.1]: 10.7.204.125 - - [11/Aug/2018:20:06:44 UTC] "GET /products HTTP/1.1" 500 939
2018-08-11T20:06:45.143819+00:00 app[web.1]: http://mab-staging.herokuapp.com/products/new -> /products
2018-08-11T20:06:45.667492+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mab-staging.herokuapp.com request_id=752f97ad-deea-41ed-af16-5a9c67f0329c fwd="68.225.227.137" dyno=web.1 connect=0ms service=20ms status=304 bytes=133 protocol=http
2018-08-11T20:06:45.668380+00:00 app[web.1]: 10.7.204.125 - - [11/Aug/2018:20:06:45 UTC] "GET /favicon.ico HTTP/1.1" 304 0
2018-08-11T20:06:45.668476+00:00 app[web.1]: http://mab-staging.herokuapp.com/products -> /favicon.ico

我有 this Heroku documentation/tutorial 中包含的所有步骤。

我已经在本地和 Heroku 上安装了 ActiveStorage 和 运行 rake db:migrate

我的products#createproducts#update方法是这样的:

 def create
    @product = Product.new(product_params)
    @product.product_image.attach(params[:product][:product_image])
    @product.save
    flash[:notice] = "Your product has been created!"
    redirect_to products_path
  end

  def update
    @product = Product.find(params[:id])
    @product.product_image.attach(params[:product][:product_image])
    if @product.update_attributes(product_params)
      redirect_to products_path
      flash[:notice] = "That product has been updated."
    else
      render :action => :edit
      flash[:alert] = "Something went terribly wrong there..."
    end
  end

我的表单域很简单:

    <div class="form-group col-xs-12">
      <%= f.file_field :product_image %>
    </div> <!-- form group -->

我的 Gemfile 中有以下内容并且有 运行 bundle installbundle update:

gem 'activestorage'
gem 'aws-sdk', '~> 3' #AWS
gem 'mini_magick', '~> 4.8'

我在 production.rbstaging.rb 中有这个:

  # Store files on Amazon S3.
  config.active_storage.service = :amazon

storage.yml中的这个:

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

amazon:
  service: S3
  access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
  secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
  region: <%= ENV['AWS_REGION'] %>
  bucket: <%= ENV['S3_BUCKET_NAME'] %>

我这样做了,尽管我并不完全理解它的作用:

 heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview

我的 product.rb 模型中有这个:

has_one_attached :product_image

谁能看出这在本地有效但在 Heroku 上无效的任何原因?我被窃听了...

附加信息

经过一些heroku logs的帮助,我有更详细的日志:

2018-08-11T21:16:51.614163+00:00 app[web.1]: Completed 500 Internal Server Error in 139ms (ActiveRecord: 21.6ms)
2018-08-11T21:16:51.617425+00:00 app[web.1]: 
2018-08-11T21:16:51.617550+00:00 app[web.1]: ActionView::Template::Error (to_model delegated to attachment, but attachment is nil):
2018-08-11T21:16:51.617809+00:00 app[web.1]: 3:   <div class="row">
2018-08-11T21:16:51.617812+00:00 app[web.1]: 4:     <div class="col-sm-3 text-center">
2018-08-11T21:16:51.617814+00:00 app[web.1]: 5:       <% if product.product_image %>
2018-08-11T21:16:51.617819+00:00 app[web.1]: 6:         <%= image_tag url_for(product.product_image), alt: product.name, style: "max-width: 100%; max-height: 200px" %>
2018-08-11T21:16:51.617822+00:00 app[web.1]: 7:       <% end %>
2018-08-11T21:16:51.617823+00:00 app[web.1]: 8:     </div>
2018-08-11T21:16:51.617825+00:00 app[web.1]: 9:
2018-08-11T21:16:51.617878+00:00 app[web.1]: 
2018-08-11T21:16:51.617936+00:00 app[web.1]: app/views/products/_product_row.html.erb:6:in `_app_views_products__product_row_html_erb__1069905907297071252_46241260'
2018-08-11T21:16:51.617938+00:00 app[web.1]: app/views/products/index.html.erb:21:in `block in _app_views_products_index_html_erb___2131941533006009981_47014040'
2018-08-11T21:16:51.617940+00:00 app[web.1]: app/views/products/index.html.erb:20:in `_app_views_products_index_html_erb___2131941533006009981_47014040'
2018-08-11T21:16:51.630658+00:00 app[web.1]: 10.148.82.74 - - [11/Aug/2018:21:16:51 UTC] "GET /products HTTP/1.1" 500 939
2018-08-11T21:16:51.630751+00:00 app[web.1]: https://www.manlyartofbbq.com/products/new -> /products

不幸的是,这看起来像是在说附件是 nil,尽管它不应该是,所以由于某种原因 product_image 没有正确上传...

尝试在 production.rb

中添加此代码
config.assets.digest = false

这个问题从未真正得到解决,但我通过删除有关 table 的数据库记录并重新上传它们来回避它。似乎是从 Paperclip 上传的照片转换为 ActiveStorage 上传的照片的问题。

<% if product.product_image %>
  <%= image_tag url_for(product.product_image), alt: product.name, style: "max-width: 100%; max-height: 200px" %>
<% end %>

在上面的代码中,`product.product_image returns 即使没有附加图像也是真实的。只需将条件更改为

<% if product.product_image.attached? %>
  <%= image_tag url_for(product.product_image), alt: product.name, style: "max-width: 100%; max-height: 200px" %>
<% end %>