Cette fois, il semble que le moment de l'enregistrement des images ait changé depuis Rails 6, alors je l'ai vérifié.
$ rails -v
Rails 6.0.2.1
$ rails active_storage:install
$ rails db:migrate
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.
Je téléchargerai l'image immédiatement.
Lorsque vous téléchargez le test .jpeg et appuyez sur le bouton Créer un utilisateur
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.
Ensuite, essayez un nouvel aperçu.
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)
 
C'est fait! !!
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