[RUBY] [Rails 6] La durée de sauvegarde des images active_strage a été modifiée.

Cette fois, il semble que le moment de l'enregistrement des images ait changé depuis Rails 6, alors je l'ai vérifié.

Vérifier la version des rails

$ rails -v
Rails 6.0.2.1

Installer Active Strage

$ rails active_storage:install
$ rails db:migrate

Se préparer à joindre une image

Je publierai le produit final.

Ajoutez un aperçu à l'itinéraire.

route.rb


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

Permet au modèle de gérer les images avec has_one_attached.

user.rb


class User < ApplicationRecord
  has_one_attached :image
end

Vient ensuite le contrôleur. Cette fois, je veux ajouter une fonction de prévisualisation, j'ai donc ajouté une action de prévisualisation.

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

Enfin, 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>

Vous êtes maintenant prêt.

Moment de l'enregistrement des images dans Rails 6

Je téléchargerai l'image immédiatement.

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

Lorsque vous téléchargez le test .jpeg et appuyez sur le bouton Créer un utilisateur

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

create est réussi. Si vous allez voir l'image téléchargée ici

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">

J'ai trouvé que l'image existe.

Non enregistré par téléchargement

Ensuite, essayez un nouvel aperçu.

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

De la même manière, téléchargez le fichier preview.jpg et appuyez sur le bouton preview pour vérifier l'image.

Puis

> @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>'

Absent! !!

> 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="Aperçu.jpg ",
 @tempfile=#<File:/tmp/RackMultipart20200522-1-ha9tz1.jpg>>

Vérifiez les paramètres. N'est-il pas enregistré simplement en téléchargeant une image?

Si vous vous référez à ce qui suit https://github.com/rails/rails/pull/33303

sur rails5

@user.image = params[:image]

C'est le moment où vous le mettez dans l'attribut!

Pas question qu'il y ait un tel changement dans les rails 6! !! Si cela reste tel quel, l'image ne peut pas être transmise à View au moment de l'aperçu (sans enregistrer l'image dans l'instance).

Quand je cherchais un bon moyen

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

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

Il y avait!!

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

essayer!

> @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="Aperçu.jpg ",
 @tempfile=#<File:/tmp/RackMultipart20200522-1-ha9tz1.jpg>>

plus loin

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

J'ai pu récupérer les données binaires avec ↑, donc si je l'encode avec Base64 et que je la passe

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

C'est fait! !!

Résumé

Je ne savais pas qu'il y avait un changement dans le moment de sauver Active Strage. Si vous souhaitez toucher l'image sans enregistrer

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

Lisez le binaire avec Base64! !! (Il n'est pas nécessaire que ce soit Base64)

S'il vous plaît laissez-moi savoir s'il existe un autre bon moyen.

Recommended Posts

[Rails 6] La durée de sauvegarde des images active_strage a été modifiée.
Le contenu de useBodyEncodingForURI a-t-il changé par rapport à Tomcat8?
La date et l'heure de java8 ont été mises à jour
[Rails] Enregistrez des images à l'aide de carrierwave
[Swift] Obtenez le moment où la valeur de textField est modifiée
[Ruby on Rails] Changez la destination de sauvegarde du recueil de gemmes * Remarque
[Rails] Vérifiez le contenu de l'objet
Explication de l'ordre des itinéraires ferroviaires
Vérifier l'état de migration des rails
[Rails] Comment résoudre le décalage temporel de created_at après la méthode de sauvegarde
Modifiez la destination d'enregistrement de l'image en S3 dans l'application Rails. Partie 2
L'identité des paramètres de rails [: id]
[Rails] Changer le nom de l'étiquette de f.label
La méthode JacocoReportBase.setClassDirectories (FileCollection) est obsolète.
[Rails] Nous avons résumé les emplacements de stockage et l'utilisation des images des développeurs et des utilisateurs.