I've found a new bug while my personally-developed app is getting pretty close to completion ... (I'm glad I noticed it before it was released).
The introduction is long, so if you want to know the solution quickly, please skip this area! !!
I implemented the image upload function such as profile image using ActiveStorage, but the following bugs were found. For example, suppose a user sets an image on a user edit page. And then suppose you want to change your password. Naturally, the user only enters the new password and that value is posted from the form on the edit page. At this time, the previously uploaded image is not set in the file selection area (file_field) of the form, so if the update action is executed in this state, the previously uploaded image will disappear and it is set in the application. It will be overwritten with the default image.
In other words, it provides the user with the worst UX that they can't keep the image changes unless they upload the image every time they edit. This has to be done, so I'll write a solution!
Add the following to the controller.
users_controller.rb
def update
@user = User.find(params[:id])
@user.avatar.attach(params[:avatar]) if @user.avatar.blank?
if @user.update(user_params)
flash[:success] = 'I updated my profile'
redirect_to @user
else
render 'edit'
end
end
Just add ** if @ user.avatar.blank? **! Actually, I didn't know how to create a cache of images already set in ActiveStorage regardless of whether I googled or googled, so as a result of thinking for myself and verifying various hypotheses, I was able to come up with this sentence and solve it. I did. (It came out with CarrierWave) I confirmed that the test also passed. (It has been confirmed that the test will fail properly if this sentence is erased)
But with this
** If you want to change the already set image normally, `@ user.avatar.bkank?`
becomes false and `@ user.avatar.attach (params [: avatar])` Isn't it possible to change the image without executing
? ** **
Do not you think so? I think. .. Even with w, the actual image is updated and the test passes, so I'm going to use this for the time being.
** If anyone understands the principle around here, I would appreciate it if you could comment. ** **
As a supplement, the test code that actually passed is posted here (only the relevant part is excerpted).
upload_image_spec.rb
require 'rails_helper'
RSpec.describe 'Image upload', type: :system do
let(:user) { FactoryBot.create(:user) }
before do
valid_login(user)
end
#Upload and save images
def upload_user_avatar(user)
visit edit_user_path(user)
attach_file 'user_avatar', "#{Rails.root}/spec/fixtures/images/test.jpg "
click_on 'save'
end
it 'Images uploaded by user should be displayed on My Page' do
upload_user_avatar(user)
expect(page).to have_selector("img[src$='test.jpg']")
end
it "The user succeeds in updating the image" do
visit edit_user_path(user)
attach_file 'user_avatar', "#{Rails.root}/spec/fixtures/images/updated_test.jpg "
click_on 'save'
expect(page).to have_selector("img[src$='updated_test.jpg']")
end
it "When editing without uploading the image, it should not be overwritten with the default image data" do
upload_user_avatar(user)
visit edit_user_path(user)
click_on 'save'
expect(page).to have_selector("img[src$='test.jpg']")
end
end
I output what I learned every day! If you have any suggestions, I would be grateful if you could comment! !!
Recommended Posts