如果在rails app中更新了特定字段,请执行操作

时间:2013-12-18 20:32:12

标签: ruby-on-rails ruby

我是Rails的新手(和Ruby一样)。如果用户将他/她的手机号码添加到她的帐户,我正试图通过Twilio触发短信进行验证:

def update
 authorize! :update, @user, :message => 'Not authorized as an administrator.'
 @user = User.find(params[:id])
 role = Role.find(params[:user][:role_ids]) unless params[:user][:role_ids].nil?
 params[:user] = params[:user].except(:role_ids)
 if @user.update_attributes(params[:user])

  if @user.mobile_changed?
    @user.update_attribute(:mobile_verified, false)
    #:message => 'You will receive an SMS shortly with verification instructions.'
    # Instantiate a Twilio client
    client = Twilio::REST::Client.new(TWILIO_CONFIG['sid'], TWILIO_CONFIG['token'])

    # Create and send an SMS message
    client.account.sms.messages.create(
        from: TWILIO_CONFIG['from'],
        to: @user.mobile,
        body: "Thanks for adding your mobile number. To verify, please reply YES to this message."
    )
  end
  @user.update_plan(role) unless role.nil?
  redirect_to users_path, :notice => "User updated."
else
  redirect_to users_path, :alert => "Unable to update user."
end
end

该帐户似乎更新正常,但我的嵌套“if”语句显然是不正确的,因为它不起作用...任何建议?谢谢!

2 个答案:

答案 0 :(得分:2)

将after_save(或after_update)回调添加到您的用户模型。更改的属性将在那里提供。

注意:您不应该从after_save回调更新当前记录,因为您可能会以无限循环结束。

class User < ActiveRecord
  before_save :reset_mobile_verification, :if => :mobile_verified_changed?
  after_save  :deliver_sms, :if => :mobile_changed?

  def reset_mobile_verification
    self.mobile_verified = false
  end

  def deliver_sms
    # Code to send SMS
  end
end

修改

我看到另一个答案已更新,以执行类似的操作,但使用after_commit回调。根据您希望应用程序的行为方式,您可以使用after_save(Twilio API错误将导致保存失败)或after_commit(Twilio API错误将导致保存失败,因为它发生在数据库COMMIT)。

答案 1 :(得分:1)

ActiveModel::Dirty方法很棘手,它们只会在对象时返回true,即,当一个或多个属性已被更改但在这些更改之前已写入数据库。保存对象后,例如第一次if语句对update_attributes的调用,它就不再是脏的,named_changed?将返回false。为了让if工作,我建议if @user.previous_changes.include?(:mobile)

编辑 - 此外,您还可以使用回调将此业务逻辑移至模型。

before_validation ->(user) { user.mobile_verified = false if user.mobile_changed? }
after_commit :send_twilio_verification, :unless => :mobile_verified, on: [:create, :update]