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