无法让用户使用 devise invitable 创建自定义消息
Can't get users to create a custom message with devise invitable
我的应用程序中有 2 个类似用户的模型:'Participant' 和 'Member'。
我试图让他们在通过 Devise Invitable 邀请其他 members/participants 时包含自定义消息。但是,我无法让它工作。
我正在关注此 official tutorial,因此我进行了以下更改以覆盖 Devise Invitable Controller,但在使用 pry 时,发送邀请时似乎未触及此自定义控制器。我做错了什么:
controllers/participants/invitations_controller.rb
class Participants::InvitationsController < Devise::InvitationsController
before_action :update_sanitized_params, only: :update
def create
binding.pry
@from = params[:from]
@subject = params[:invite_subject]
@content = params[:invite_content]
@participant = Participant.invite!(params[:user], current_member) do |u| #XXX Check if :user should be changed
u.skip_invitation = true
end
ParticipantInvitationNotificationMailer.invite_message(@participant, @from, @subject, @content).deliver if @participant.errors.empty?
@participant.invitation_sent_at = Time.now.utc # mark invitation as delivered
if @participant.errors.empty?
flash[:notice] = "successfully sent invite to #{@participant.email}"
respond_with @participant, :location => root_path
else
render :new
end
end
def update
respond_to do |format|
format.js do
invitation_token = Devise.token_generator.digest(resource_class, :invitation_token, update_resource_params[:invitation_token])
self.resource = resource_class.where(invitation_token: invitation_token).first
resource.skip_password = true
resource.update_attributes update_resource_params.except(:invitation_token)
end
format.html do
super
end
end
end
protected
def update_sanitized_params
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:password, :password_confirmation, :invitation_token, :username])
end
end
config/routes.rb
Rails.application.routes.draw do
devise_for :members, controllers: { invitations: "members/invitations" }
devise_for :participants, controllers: { invitations: "participants/invitations" }
end
models/participant.rb
class Participant < ApplicationRecord
attr_reader :raw_invitation_token
end
mailers/notification_mailer.rb
class NotificationMailer < ApplicationMailer
def invite_message(user, from, subject, content)
@user = user
@token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => @token)
mail(:from => from, :bcc => from, :to => @user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.last_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
如果我发送 invitation:with Participant.invite!({:email => 'example@email.com'}, Member.first)
邀请将通过控制台中显示的默认邮件程序发送,而不是通过我的新邮件程序发送。为什么?
Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb (0.6ms)
Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb (0.8ms)
终于可以解决这个问题了。
它最终成为一个新手错误 我在想调用 invite!
方法与自定义邀请控制器中的自定义 create
方法有什么关系。
我当然必须通过指定的路线到达 create
方法,并在该方法内阻止邀请!使用以下代码通过默认邮件程序发送电子邮件的方法(在 Devise Invitable 文档中明确规定):
@participant = Participant.invite!({:email => @invitation_draft.email}, current_member) do |u|
u.skip_invitation = true
end
之后我们可以在创建方法中调用任何自定义邮件程序。
我的应用程序中有 2 个类似用户的模型:'Participant' 和 'Member'。 我试图让他们在通过 Devise Invitable 邀请其他 members/participants 时包含自定义消息。但是,我无法让它工作。
我正在关注此 official tutorial,因此我进行了以下更改以覆盖 Devise Invitable Controller,但在使用 pry 时,发送邀请时似乎未触及此自定义控制器。我做错了什么:
controllers/participants/invitations_controller.rb
class Participants::InvitationsController < Devise::InvitationsController
before_action :update_sanitized_params, only: :update
def create
binding.pry
@from = params[:from]
@subject = params[:invite_subject]
@content = params[:invite_content]
@participant = Participant.invite!(params[:user], current_member) do |u| #XXX Check if :user should be changed
u.skip_invitation = true
end
ParticipantInvitationNotificationMailer.invite_message(@participant, @from, @subject, @content).deliver if @participant.errors.empty?
@participant.invitation_sent_at = Time.now.utc # mark invitation as delivered
if @participant.errors.empty?
flash[:notice] = "successfully sent invite to #{@participant.email}"
respond_with @participant, :location => root_path
else
render :new
end
end
def update
respond_to do |format|
format.js do
invitation_token = Devise.token_generator.digest(resource_class, :invitation_token, update_resource_params[:invitation_token])
self.resource = resource_class.where(invitation_token: invitation_token).first
resource.skip_password = true
resource.update_attributes update_resource_params.except(:invitation_token)
end
format.html do
super
end
end
end
protected
def update_sanitized_params
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:password, :password_confirmation, :invitation_token, :username])
end
end
config/routes.rb
Rails.application.routes.draw do
devise_for :members, controllers: { invitations: "members/invitations" }
devise_for :participants, controllers: { invitations: "participants/invitations" }
end
models/participant.rb
class Participant < ApplicationRecord
attr_reader :raw_invitation_token
end
mailers/notification_mailer.rb
class NotificationMailer < ApplicationMailer
def invite_message(user, from, subject, content)
@user = user
@token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => @token)
mail(:from => from, :bcc => from, :to => @user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.last_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
如果我发送 invitation:with Participant.invite!({:email => 'example@email.com'}, Member.first)
邀请将通过控制台中显示的默认邮件程序发送,而不是通过我的新邮件程序发送。为什么?
Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb (0.6ms)
Rendering /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0@pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb (0.8ms)
终于可以解决这个问题了。
它最终成为一个新手错误 我在想调用 invite!
方法与自定义邀请控制器中的自定义 create
方法有什么关系。
我当然必须通过指定的路线到达 create
方法,并在该方法内阻止邀请!使用以下代码通过默认邮件程序发送电子邮件的方法(在 Devise Invitable 文档中明确规定):
@participant = Participant.invite!({:email => @invitation_draft.email}, current_member) do |u|
u.skip_invitation = true
end
之后我们可以在创建方法中调用任何自定义邮件程序。