我在rails上学习ruby,在aasm回调和actionmailer方面遇到麻烦。我有旅馆的模特。这是一个代码:
class Hotel < ActiveRecord::Base
include AASM
scope :approved_hotels, -> { where(aasm_state: "approved") }
has_many :comments
belongs_to :user, :counter_cache => true
has_many :ratings
belongs_to :address
aasm do
state :pending, initial: true
state :approved
state :rejected
event :approve, :after => :send_email do
transitions from: :pending, to: :approved
end
event :reject, :after => :send_email do
transitions from: :pending, to: :rejected
end
end
def send_email
end
end正如你所看到的,当酒店状态发生变化时,用户必须收到电子邮件,他补充说。这是我写的,但这不是解决方案,因为每次管理员更新酒店时,用户都会收到电子邮件。
class HotelsController < ApplicationController
before_filter :authenticate_user!, except: [:index, :show, :top5hotels]
def update
@hotel = Hotel.find(params[:id])
if @hotel.aasm_state == "pending"
@hotel.aasm_state = params[:state]
UserMailer.changed_state_email(current_user, @hotel.name,
@hotel.aasm_state).deliver
end
if @hotel.update_attributes!(params[:hotel])
redirect_to admin_hotel_path(@hotel), notice: "Hotel was successfully updated."
else
render "edit"
end
end
end所以我想我需要使用回调,但我不知道怎么打
UserMailer.changed_state_email(current_user, @hotel.name,
@hotel.aasm_state).deliver从模特那里。我试过了
UserMailer.changed_state_email(User.find(:id), Hotel.find(:name),
Hotel.find(aasm_state)).deliver但那不管用。我真的没有选择了,我在寻求任何帮助。谢谢!
发布于 2015-05-31 08:23:04
您不能使用回调,因为您的current_user是控制器上下文的一部分,并且不能访问模型上下文中的请求信息。
无论如何,即使您可以使用回调,在这种情况下,我强烈鼓励您遵循另一条路径。ActiveRecord回调应该很少使用,特别是对于涉及到与其他对象或资源的交互(例如邮件或级联更新)的代码,您应该避免使用它们。其风险是,即使不需要回调(例如测试),也会触发回调,或者当项目复杂性增加时,回调将与其他回调发生冲突。
在这种情况下,解决方案非常简单。在模型中定义一个新方法(我现在不向您介绍服务对象.)你用来改变状态和发送电子邮件。
class Hotel
def user_state_change(user, new_state)
return unless pending? && new_state.present?
if update_attribute(:aasm_state, new_state)
UserMailer.changed_state_email(user, name, aasm_state).deliver
end
end
end你的控制器会变成
class HotelsController < ApplicationController
before_filter :authenticate_user!, except: [:index, :show, :top5hotels]
def update
@hotel = Hotel.find(params[:id])
@hotel.user_state_change(current_user, params[:state])
if @hotel.update_attributes!(params[:hotel])
redirect_to admin_hotel_path(@hotel), notice: "Hotel was successfully updated."
else
render "edit"
end
end
end另外,您可能希望使用状态机转换方法,而不是更改state属性。实际上,使用状态机转换将确保转换验证被触发。
https://stackoverflow.com/questions/30555059
复制相似问题