[RUBY] [Rails 6] Das Speicher-Timing von active_strage-Bildern wurde geändert.

Dieses Mal scheint sich das Timing für das Speichern von Bildern von Rails 6 geändert zu haben, also habe ich es überprüft.

Überprüfen Sie die Rails-Version

$ rails -v
Rails 6.0.2.1

Installieren Sie Active Strage

$ rails active_storage:install
$ rails db:migrate

Vorbereiten des Anhängens eines Bildes

Ich werde das Endprodukt veröffentlichen.

Vorschau zur Route hinzufügen.

route.rb


Rails.application.routes.draw do
  resources :users do
    collection do
      post :preview
      patch :preview
    end
  end
end

Ermöglicht dem Modell, Bilder mit has_one_attached zu verarbeiten.

user.rb


class User < ApplicationRecord
  has_one_attached :image
end

Als nächstes kommt der Controller. Dieses Mal möchte ich eine Vorschau-Funktion hinzufügen, also habe ich eine Vorschau-Aktion hinzugefügt.

user_controller.rb


class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end
.
.
.
.
  def preview
    @user = User.new(user_params)
    image_binary = ''
    if @user.image.attached?
      image_binary = @user.attachment_changes['image'].attachable.read
    else
      saved_user = User.find_by(id: params[:id])
      if saved_user.present? && saved_user.image.attached?
        image_binary = saved_user.image.blob.download
      end
    end
    @image_enconded_by_base64 = Base64.strict_encode64(image_binary)

    render template: 'users/_preview', layout: 'application'
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def user_params
      params.require(:user).permit(:name, :image)
    end
end

Schließlich HTML.

ruby:new.html.erb



<h1>New User</h1>

<%= render 'form', user: @user %>

<%= link_to 'Back', users_path %>

ruby:_form.html.erb



<%= form_with(model: user, local: true) do |form| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
        <% user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
    <%= form.label :image %>
    <%= form.file_field :image %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

ruby:show.html.erb



<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
  <% if @user.image.attached? %>
    <%= image_tag @user.image %>
  <% end %>
</p>

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

ruby:_preview.html.erb


<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
  <% if action_name == 'preview' %>
    <img src="data:image/png;base64,<%= @image_enconded_by_base64 %>" />
  <% else %>
    <%= image_tag @member.image %>
  <% end %>
</p>

Sie sind jetzt bereit.

Zeitpunkt des Speicherns von Bildern in Rails 6

Ich werde das Bild sofort hochladen.

スクリーンショット 2020-05-21 18.04.06.png

Wenn Sie die Test-JPEG-Datei hochladen und auf die Schaltfläche "Benutzer erstellen" klicken

スクリーンショット 2020-05-21 18.18.57.png

erstellen ist erfolgreich. Wenn Sie das hier hochgeladene Bild sehen möchten

irb(main):005:0> @user.image.attachment
  ActiveStorage::Attachment Load (1.5ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "User"], ["name", "image"], ["LIMIT", 1]]
=> #<ActiveStorage::Attachment id: 1, name: "image", record_type: "User", record_id: 1, blob_id: 1, created_at: "2020-05-21 09:04:12">

Ich habe festgestellt, dass das Bild existiert.

Nicht per Upload gespeichert

Versuchen Sie dann eine neue Vorschau.

スクリーンショット 2020-05-21 18.20.20.png

Laden Sie auf die gleiche Weise die Datei template.jpg hoch und klicken Sie auf die Schaltfläche "Vorschau", um das Bild zu überprüfen.

Dann

> @user.image.attachment
NameError: uninitialized constant #<Class:0x00007fd450065780>::Analyzable
from /usr/local/bundle/gems/activestorage-6.0.3.1/app/models/active_storage/blob.rb:26:in `<class:Blob>'

Abwesend! !!

> params[:user][:image]
=> #<ActionDispatch::Http::UploadedFile:0x000055892ec2b598
 @content_type="image/jpeg",
 @headers=
  "Content-Disposition: form-data; name=\"user[image]\"; filename=\"\xE3\x83\x95\xE3\x82\x9A\xE3\x83\xAC\xE3\x83\x92\xE3\x82\x99\xE3\x83\xA5\xE3\x83\xBC.jpg\"\r\nContent-Type: image/jpeg\r\n",
 @original_filename="Vorschau.jpg ",
 @tempfile=#<File:/tmp/RackMultipart20200522-1-ha9tz1.jpg>>

Überprüfen Sie die Parameter. Wird es nicht einfach durch Hochladen eines Bildes gespeichert?

Wenn Sie sich auf Folgendes beziehen https://github.com/rails/rails/pull/33303

auf Schienen5

@user.image = params[:image]

Es ist das Timing, wenn Sie es in das Attribut setzen!

Auf keinen Fall gibt es eine solche Änderung der Schienen 6! !! Wenn dies unverändert bleibt, kann das Bild zum Zeitpunkt der Vorschau nicht an View übergeben werden (ohne das Bild in der Instanz zu speichern).

Als ich nach einem guten Weg suchte

・ Https://github.com/rails/rails/pull/33303

・ Https://stackoverflow.com/questions/57564796/reading-from-active-storage-attachment-before-save

dort gab es!!

record.attachment_changes['<attributename>'].attachable

Versuchen!

> @user.attachment_changes['image'].attachable
=> #<ActionDispatch::Http::UploadedFile:0x000055892ec2b598
 @content_type="image/jpeg",
 @headers=
  "Content-Disposition: form-data; name=\"user[image]\"; filename=\"\xE3\x83\x95\xE3\x82\x9A\xE3\x83\xAC\xE3\x83\x92\xE3\x82\x99\xE3\x83\xA5\xE3\x83\xBC.jpg\"\r\nContent-Type: image/jpeg\r\n",
 @original_filename="Vorschau.jpg ",
 @tempfile=#<File:/tmp/RackMultipart20200522-1-ha9tz1.jpg>>

des Weiteren

@user.attachment_changes['image'].attachable.read

Ich konnte die Binärdaten mit ↑ abrufen, wenn ich sie also mit Base64 codiere und übergebe

@image_enconded_by_base64 = Base64.strict_encode64(@user.attachment_changes['image'].attachable.read)
スクリーンショット 2020-05-22 10.48.00.png

Es ist fertig! !!

Zusammenfassung

Ich wusste nicht, dass sich der Zeitpunkt für das Speichern von Active Strage geändert hat. Wenn Sie das Bild berühren möchten, ohne es zu speichern

record.attachment_changes['<attributename>'].attachable.read

Lesen Sie die Binärdatei mit Base64! !! (Es muss nicht Base64 sein)

Bitte lassen Sie mich wissen, ob es einen anderen guten Weg gibt.

Recommended Posts

[Rails 6] Das Speicher-Timing von active_strage-Bildern wurde geändert.
Hat sich der Inhalt von useBodyEncodingForURI von Tomcat8 geändert?
Das Datum und die Uhrzeit von java8 wurden aktualisiert
[Schienen] Speichern Sie Bilder mit Carrierwave
[Swift] Ermittelt das Timing, wenn der Wert von textField geändert wird
[Ruby on Rails] Ändere das Speicherziel von Gem Refile * Hinweis
[Schienen] Überprüfen Sie den Inhalt des Objekts
Erläuterung der Reihenfolge der Schienenrouten
Überprüfen Sie den Migrationsstatus von Schienen
[Rails] So lösen Sie die Zeitverzögerung von created_at nach der Speichermethode
Ändern Sie das Speicherziel des Bildes in der Rails-App in S3. Teil 2
Die Identität der Schienenparameter [: id]
[Rails] Ändern Sie den Labelnamen von f.label
Die Methode JacocoReportBase.setClassDirectories (FileCollection) ist veraltet.
[Rails] Wir haben die Speicherorte und die Verwendung von Entwickler- und Benutzerimages zusammengefasst.