URI::InvalidURIError (неверный URI(это не URI?): ноль) Active Storage service_url

Информация о конфигурации

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

person Imran Ahmad    schedule 27.02.2020    source источник


Ответы (5)


Я столкнулся с той же проблемой в 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

person Remon Oldenbeuving    schedule 31.03.2021
comment
То же самое здесь, в rails 6.0, при исправлении RepresentationsController для мультитенантного приложения. - person estani; 21.04.2021
comment
Это также работает при использовании на модели? - person s89_; 28.07.2021

В итоге я включил include Rails.application.routes.url_helpers в контроллер и использовал rails_blob_url(avatar.image). Я также добавил эту строку в файл маршрутов. Я сделаю рефакторинг позже.

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

person Laah Lima    schedule 17.07.2020

Согласно документации https://api.rubyonrails.org/classes/ActiveStorage/Variant.html на processed.service_url: Это создаст и обработает вариант большого двоичного объекта аватара, который ограничен высотой и шириной 100. Затем он загрузит указанный вариант в службу в соответствии с производным ключом большого двоичного объекта. и трансформации.

Также: 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, который представляет собой веб-службу, в данном случае S3.

Я думаю (со страхом ошибиться и потерять несколько баллов), что не стоит использовать его на локалке, только на проде, как вы сказали с S3. Похоже, что Диск не считается службой (по понятным причинам), нужно больше копаться в коде (сейчас просто занимаюсь этой проблемой, он работает, если я устанавливаю <%= image_tag category.image.variant(resize_to_fill: [400, 400]) %>, но не работает на <%= image_tag category.image.variant(resize_to_fill: [400, 400]).processed.service %>, на локальном хосте, но я могу получить доступ к .processed, это всего лишь .service, который терпит неудачу).

Вы сделали что-нибудь еще, чтобы заставить его работать на локальном? Я думаю, вы также можете добавить условие для проверки среды, в которой он работает.

person pablomarti    schedule 09.08.2020

лучший способ получить URL-адрес объясняется в этом ответе: https://stackoverflow.com/a/53547638

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

person Iuri G.    schedule 29.12.2020
comment
я получаю NoMethodError (undefined method 'variation' for #<ActiveStorage::Attached::One:0x00007fcb3c82ce18>) - person Dorian; 31.12.2020
comment
У вас опечатки. Это "вариант", а не "вариация" - person Iuri G.; 01.01.2021

В итоге я использовал url_for:

Rails.application.routes.url_helpers.url_for(Event.last.image)
person Dorian    schedule 30.12.2020