首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在aasm回调中调用ActionMailer方法?

如何在aasm回调中调用ActionMailer方法?
EN

Stack Overflow用户
提问于 2015-05-31 07:46:47
回答 1查看 358关注 0票数 2

我在rails上学习ruby,在aasm回调和actionmailer方面遇到麻烦。我有旅馆的模特。这是一个代码:

代码语言:javascript
复制
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

正如你所看到的,当酒店状态发生变化时,用户必须收到电子邮件,他补充说。这是我写的,但这不是解决方案,因为每次管理员更新酒店时,用户都会收到电子邮件。

代码语言:javascript
复制
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

所以我想我需要使用回调,但我不知道怎么打

代码语言:javascript
复制
UserMailer.changed_state_email(current_user, @hotel.name, 
        @hotel.aasm_state).deliver

从模特那里。我试过了

代码语言:javascript
复制
UserMailer.changed_state_email(User.find(:id), Hotel.find(:name), 
        Hotel.find(aasm_state)).deliver

但那不管用。我真的没有选择了,我在寻求任何帮助。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-31 08:23:04

您不能使用回调,因为您的current_user是控制器上下文的一部分,并且不能访问模型上下文中的请求信息。

无论如何,即使您可以使用回调,在这种情况下,我强烈鼓励您遵循另一条路径。ActiveRecord回调应该很少使用,特别是对于涉及到与其他对象或资源的交互(例如邮件或级联更新)的代码,您应该避免使用它们。其风险是,即使不需要回调(例如测试),也会触发回调,或者当项目复杂性增加时,回调将与其他回调发生冲突。

在这种情况下,解决方案非常简单。在模型中定义一个新方法(我现在不向您介绍服务对象.)你用来改变状态和发送电子邮件。

代码语言:javascript
复制
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

你的控制器会变成

代码语言:javascript
复制
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属性。实际上,使用状态机转换将确保转换验证被触发。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30555059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档