ruby on rails - How to call ActionMailer method in aasm callback? -
im learning ruby on rails , have trouble aasm callbacks , actionmailer. have hotels model. heres code:
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 state :pending, initial: true state :approved state :rejected event :approve, :after => :send_email transitions from: :pending, to: :approved end event :reject, :after => :send_email transitions from: :pending, to: :rejected end end def send_email end end
as see user has email when state of hotel added changed. heres wrote not solution cos user gets emails every time admin updates hotel "pending" state.
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 updated." else render "edit" end end end
so think need use callback dont know how call
usermailer.changed_state_email(current_user, @hotel.name, @hotel.aasm_state).deliver
from model. tried
usermailer.changed_state_email(user.find(:id), hotel.find(:name), hotel.find(aasm_state)).deliver
but doesnt work. im out of options , looking help. thanks!
you can't use callback because have current_user
part of controller context, , can't access request information in model context.
anyway, if use callback, in case encourage follow different path. activerecord callbacks should used, in particular should avoid them code involves interaction other objects or resources such mailers or cascade update. risk callback triggered when don't need (e.g. tests) increasing overhead, or conflict other callbacks when complexity of project increase.
in case solution simple. define new method in model (i'm not introducing service objects now...) use change state , deliver email.
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
your controller become
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 updated." else render "edit" end end end
as side note, may want use state machine transition methods, rather changing state attribute. in fact, using state machine transition ensure transition validation triggered.
Comments
Post a Comment