【问题标题】:URI::InvalidURIError (bad URI(is not URI?): nil) Active Storage service_urlURI::InvalidURIError (bad URI(is not URI?): nil) Active Storage service_url
【发布时间】:2020-06-11 00:06:24
【问题描述】:

配置信息

rails version 6.0
ruby version 2.7.0
gem 'image_processing', '~> 1.2'

storage.yml

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

development.rb

config.active_storage.service = :local
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

仅当我使用 service= :local 时才会出现此异常。 使用 AWS S3 配置,使用 :amazon 时它可以正常工作。

user.rb 模型

  has_one_attached :avatar
  
  #throwing exception
  def avatar_urls
    {
      original: avatar.service_url
    } if avatar.attachment
  end

访问avatar_urls 时抛出异常(URI::InvalidURIError (bad URI(is not URI?): nil) )。但是,如果我将我的 avatars_url 方法更改为跟随,它工作正常。

  #working method
  def avatar_urls
    {
      thumbnail: url_for(avatar.variant(resize: "100x100").processed)
    } if avatar.attachment
  end

这是踪迹:

Disk Storage (5056.7ms) Generated URL for file at key: variants/i5w1ie6ro07mib4qcdn30lmik6wn/2a7fa5dad6ac227a16e961cbd12ca6f35f1d7947f56a97754d5e22c1a0fd3372 ()
cb_app_container | Completed 500 Internal Server Error in 9523ms (ActiveRecord: 580.9ms | Allocations: 1185509)
cb_app_container | URI::InvalidURIError (bad URI(is not URI?): nil):
cb_app_container | app/models/user.rb:53:in `avatar_urls'
cb_app_container | app/models/user.rb:27:in `user_json'
cb_app_container | app/controllers/api/v1/users_controller.rb:13:in `update'
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]    (61.6ms)  BEGIN
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]   ActiveStorage::Blob Update (10.3ms)  UPDATE "active_storage_blobs" SET "metadata" = $1 WHERE "active_storage_blobs"."id" = $2  [["metadata", "{\"identified\":true,\"width\":1952,\"height\":3264,\"analyzed\":true}"], ["id", 45]]
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]    (19.6ms)  COMMIT
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee] Performed ActiveStorage::AnalyzeJob (Job ID: 33448db4-cf54-4677-906c-06b59f1579ee) from Async(default) in 6916.06ms

【问题讨论】:

    标签: ruby-on-rails rails-activestorage ruby-on-rails-6


    【解决方案1】:

    对于在 Rails 5.x 上遇到此问题的任何人,您需要为 service_url 定义主机。这是 ActiveStorage 使用的代码:https://github.com/rails/rails/blob/v5.2.6/activestorage/app/controllers/active_storage/base_controller.rb

    关键行是:ActiveStorage::Current.host = request.base_url

    在致电avatar.service_url之前坚持这一点

    大警告:您可能不想直接致电avatar.service_urlurl_for(...) 自动为您处理所有这些管道。

    【讨论】:

      【解决方案2】:

      我在 Rails 6.1 中遇到了同样的问题,发现我必须在我的控制器中包含一个特殊的关注点才能让 ActiveStorage 知道当前主机:

      module Api
        module V1
          class ApiController < ActionController::API
            # Make ActiveStorage aware of the current host (used in url helpers)
            include ActiveStorage::SetCurrent
          end
        end
      end
      
      

      【讨论】:

      • Rails 6.0 中的情况相同,同时为多租户应用程序修补 RepresentationsController。
      • 在模型上使用时这也有效吗?
      • 这在 Rails 6.1 中对我有用。我将包含添加到我的 GraphQL 控制器中,并使用了此代码 object.file.preview(resize_to_limit: [480, 960]).processed.url
      • @emptywalls 你是我的救星,我需要那个processed 方法,非常感谢
      【解决方案3】:

      我最终使用了url_for

      Rails.application.routes.url_helpers.url_for(Event.last.image)
      

      【讨论】:

        【解决方案4】:

        此答案解释了获取 url 的更好方法:https://stackoverflow.com/a/53547638

        Rails.application.routes.url_helpers.rails_representation_url(picture_of_car.variant(resize: "300x300").processed, only_path: true)

        【讨论】:

        • 我收到NoMethodError (undefined method 'variation' for #&lt;ActiveStorage::Attached::One:0x00007fcb3c82ce18&gt;)
        • 你有错别字。这是“变体”而不是“变体”
        【解决方案5】:

        根据processed.service_url 上的文档https://api.rubyonrails.org/classes/ActiveStorage/Variant.html这将创建并处理限制为高度和宽度为 100 的化身 blob 的变体。然后它将根据该变体将所述变体上传到服务到 blob 的派生键和转换。

        还有:https://api.rubyonrails.org/classes/ActiveStorage/Variant.html#method-i-service_url

        查看 GH 的代码,我可以看到 service 来自 https://github.com/rails/rails/blob/fbe2433be6e052a1acac63c7faf287c52ed3c5ba/activestorage/app/models/active_storage/blob.rb,它代表 Web 服务,在本例中为 S3。

        我认为(担心会出错并失去一些分数)你不应该在本地使用它,只能像你对 S3 所说的那样在 prod 上使用它。似乎磁盘不被视为一项服务(出于显而易见的原因),必须深入研究代码(现在只是处理这个问题,如果我在本地主机上设置&lt;%= image_tag category.image.variant(resize_to_fill: [400, 400]) %&gt; 但在&lt;%= image_tag category.image.variant(resize_to_fill: [400, 400]).processed.service %&gt; 上失败,则它可以工作,但是我可以访问.processed,只是.service 失败)。

        您是否采取了其他措施使其在本地运行?我想你也可以添加一个条件来检查它正在运行的环境。

        【讨论】:

          【解决方案6】:

          我最终将include Rails.application.routes.url_helpers 包含在控制器中并使用了rails_blob_url(avatar.image)。我还在路由文件中添加了这一行。我稍后会重构它。

          Rails.application.routes.default_url_options[:host] = 'localhost:3000'

          【讨论】:

            猜你喜欢
            • 2017-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-09
            • 2018-06-12
            • 2012-02-23
            • 2011-07-19
            相关资源
            最近更新 更多