我是 Rails 的新手,在這個專案中,我想構建一個程式,允許您創建用戶帳戶并將個人資料圖片上傳到它。然后它會向您發送一封電子郵件以通知您的上傳成功。
- 用戶帳戶由 Devise 處理
- 使用 Active Storage 頭像附件處理影像上傳
在 Devise 上,此類附件上傳在連接到 Devise::RegistrationsController 的編輯頁面中處理:
# frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
# def new
# super
# end
# POST /resource
# def create
# super
# end
# GET /resource/edit
# def edit
# super
# end
# PUT /resource
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
resource_updated = update_resource(resource, account_update_params)
yield resource if block_given?
if resource_updated
set_flash_message_for_update(resource, prev_unconfirmed_email)
bypass_sign_in resource, scope: resource_name if sign_in_after_change_password?
respond_with resource, location: after_update_path_for(resource)
else
clean_up_passwords resource
set_minimum_password_length
respond_with resource
end
binding.irb
# PAY ATTENTION TO HERE
if @user.avatar.attached?
UserMailer.upload_email(@user).deliver
end
end
# DELETE /resource
# def destroy
# @user = User.find(params[:user_id])
# puts @user
# if @user.destroy
# redirect_to root_path
# end
# end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# end
# protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:avatar])
end
# The path used after sign up.
# def after_sign_up_path_for(resource)
# super(resource)
# end
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
end
編輯.html.erb:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
# PAY ATTENTION TO HERE
<div class="field">
<%= f.label :avatar %><br />
<%= f.file_field :avatar %>
</div>
<div >
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>
<div >
<%= f.submit "Update"%>
</div>
<% end %>
我希望您注意registrations_controller 中的更新操作,尤其是以下行:
if @user.avatar.attached?
UserMailer.upload_email(@user).deliver
end
現在這是完全錯誤的,即使它在您第一次上傳影像時發送電子郵件,之后一旦您單擊“更新”而不上傳任何附件,它仍然會發送電子郵件,因為唯一的條件是“avatar.attached?”,它回傳true 因為已經附加了影像。
現在,多虧了 binding.irb,我可以檢查在添加檔案和沒有添加檔案時傳遞給更新的引數。
- 添加檔案時:
irb(#<Users::RegistrationsController:0x0000023b767c6790>):001:0> params
=> #<ActionController::Parameters {"_method"=>"put", "authenticity_token"=>"6O0jz5U2XWfb4pu_An3pMh1BUq5o71n0U2_E3zWy0-efqm0orl_Vi5o_jo1B2o4Oc11AyRt-Zd6XBPJnmXpr8w", "user"=>#<ActionController::Parameters {"email"=>"***@hotmail.com", "avatar"=>#<ActionDispatch::Http::UploadedFile:0x0000023b767c5660 @tempfile=#<Tempfile:C:/Users/pc/AppData/Local/Temp/RackMultipart20220903-13632-upo8fa.png>, @original_filename="WhatsApp Image 2022-08-06 at 23.03.10.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"WhatsApp Image 2022-08-06 at 23.03.10.png\"\r\nContent-Type: image/png\r\n">, "password"=>"", "password_confirmation"=>"", "current_password"=>"password"} permitted: false>, "commit"=>"Update", "controller"=>"users/registrations", "action"=>"update"} permitted: false>
- 沒有時:
irb(#<Users::RegistrationsController:0x0000023b763ea950>):001:0> params
=> #<ActionController::Parameters {"_method"=>"put", "authenticity_token"=>"NCJA7QSTCuAVdogoAN9Z96B4EsJIRoGQyvwmNPVqvu1DZQ4KP_qCDFSrnRpDeD7LzmQApTvXvboOlxCMWaIG-Q", "user"=>#<ActionController::Parameters {"email"=>"***@hotmail.com", "password"=>"", "password_confirmation"=>"", "current_password"=>"123456"} permitted: false>, "commit"=>"Update", "controller"=>"users/registrations", "action"=>"update"} permitted: false>
如您所見,當有一個檔案添加到 f.file_field 時,您可以在 params 中看到“avatar”“@tempfile”“original_filename”之類的內容。
所以我的邏輯是,在更新操作之前,我應該檢查是否有檔案添加到 f.file_field 中。如果添加了檔案,一旦用戶更新,我應該發送電子郵件通知它已成功上傳,但我不知道該怎么做。有任何想法嗎?
- 我的代碼的其余相關部分如下:
用戶控制器:
class UsersController < ApplicationController
before_action :set_user
def profile;end
private
def set_user
@user = User.find(params[:id])
end
end
用戶模型(user.rb):
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one_attached :avatar
end
我的表(schema.rb):
ActiveRecord::Schema[7.0].define(version: 2022_08_28_175416) do
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.string "service_name", null: false
t.bigint "byte_size", null: false
t.string "checksum"
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "active_storage_variant_records", force: :cascade do |t|
t.bigint "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
end
uj5u.com熱心網友回復:
有幾種方法可以做到這一點。但我的建議是在模型上創建一個after_save回呼User,如下所示:
after_save :notify_new_avatar
def notify_new_avatar
notify if new_avatar?
end
def notify
UserMailer.notify_new_avatar
end
def new_avatar?
# how do we determine this?
end
要確定是否上傳了新頭像,我建議使用Active Model Dirty的功能。
我不清楚在您的應用程式中表示頭像更改的屬性是什么,但User.avatar_id_previously_changed?可能會為您提供所需的檢測。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/505030.html
標籤:轨道上的红宝石 红宝石 设计 rails-activestorage ruby-on-rails-7
上一篇:將表格從html匯入谷歌表格
下一篇:使用Bootstrap5.1在Rails7.0.2.3應用程式中覆寫Bootstrapmodal的關閉功能的最佳方法
