2

有人问了一个类似的问题,但没有一个解决方案对我有用。我在solidus中构建一个应用程序,每次创建产品时都需要生成二维码。我使用 rqr gem,然后尝试将生成的rqrcode png 附加到 Active Storage 中的产品。

每当我尝试渲染图像时,我都会收到以下错误。

Can't resolve image into URL: undefined method `attachment_url' for #<ActionView::Base:0x007fd104542310>

<%= image_tag(@product.qr_code) if @product.qr_code.attached? %>

创建产品时,我会在模型中生成一个 qr_code,如下所示。

has_one_attached :qr_code
after_create :generate_qr
   
    def generate_qr
      qrcode = RQRCode::QRCode.new("localhost:3000/products/#{self.slug}")
      # NOTE: showing with default options specified explicitly
      png = qrcode.as_png(
        bit_depth: 1,
        border_modules: 4,
        color_mode: ChunkyPNG::COLOR_GRAYSCALE,
        color: "black",
        file: nil,
        fill: "white",
        module_px_size: 6,
        resize_exactly_to: false,
        resize_gte_to: false,
        size: 120
      )

      image_name = SecureRandom.hex
      IO.binwrite("tmp/#{image_name}.png", png.to_s)
      
      blob = ActiveStorage::Blob.create_after_upload!(
        io: File.open("tmp/#{image_name}.png"),
        filename: image_name,
        content_type: 'png'
      )

      self.qr_code.attach(blob)
    end

我也试过直接用 attach 方法附加

 self.qr_code.attach(
         io: File.open("tmp/#{image_name}.png"),
         filename: image_name,
         content_type: 'png'
       )

当我运行时,@product.qr_code.attached?true知道附加的 Active Record 正在工作。

我检查了我所有的配置文件,一切似乎都是正确的。

config/storage.yml

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

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
config.active_storage.service = :local <--- congif/enivronments/development.rb
config.active_storage.service = :local<--- congif/enivronments/production.rb
config.active_storage.service = :test <--- congif/enivronments/test.rb

有谁知道可能导致此错误消息的原因?谢谢。

4

1 回答 1

1

我能够重现您的问题,发现您可以通过从其表示对象中获取 QR 码的 URL 来呈现产品的 QR 码:

<%= image_tag(@product.qr_code.representation(
    resize_to_limit: [100, 100]).processed.url) %>

请参阅https://edgeguides.rubyonrails.org/active_storage_overview.html#lazy-vs-immediate-loading了解更多详情。

这就是我覆盖 Product 模型的方式:

# app/overrides/store/product/can_generate_qr.rb
module Store
  module Spree
    module Product
      module CanGenerateQR
        def self.prepended(base)
          base.has_one_attached :qr_code
          base.after_create :generate_qr
        end

        def generate_qr
          qrcode = RQRCode::QRCode.new("localhost:3000/products/#{self.slug}")
          # NOTE: showing with default options specified explicitly
          png = qrcode.as_png(
            bit_depth: 1,
            border_modules: 4,
            color_mode: ChunkyPNG::COLOR_GRAYSCALE,
            color: "black",
            file: nil,
            fill: "white",
            module_px_size: 6,
            resize_exactly_to: false,
            resize_gte_to: false,
            size: 120
          )

          image_name = SecureRandom.hex
          IO.binwrite("tmp/#{image_name}.png", png.to_s)

          blob = ActiveStorage::Blob.create_after_upload!(
            io: File.open("tmp/#{image_name}.png"),
            filename: image_name,
            content_type: 'png'
          )

          self.qr_code.attach(blob)
        end

        ::Spree::Product.prepend self
      end
    end
  end
end
于 2022-02-16T10:28:55.783 回答