简体   繁体   English

使用state_machine gem,有没有办法使事件私有/受保护?

[英]With the state_machine gem, is there a way to make the events private/protected?

I am wondering if there's a way to make the state event private when using the state_machine gem? 我想知道在使用state_machine gem时是否有办法使状态事件变为私有?

I have a three states 我有三个州

unpaid, pending, paid. 未付,待定,已付款。

When a receipt is in unpaid then an event can be fired to charge the user. 如果收据未付,则可以触发事件以向用户收费。 This switches the receipt to pending (while it talks to the merchant service) Then once it is done, it would call the pay event and thus set the state to paid. 这会将收据切换为待处理(当​​它与商家服务对话时)然后一旦完成,它将调用付费事件,从而将状态设置为付款。

The user of the receipt class can technically call the pay event, which would switch the receipt to paid even though it didn't run through the merchant. 收据类的用户可以在技术上调用付费事件,即使它没有通过商家运行,也会将收据切换为付款。

NOTE: THIS IS A CONTRIVED EXAMPLE... 注意:这是一个反对的例子......

I am a strong believer in private and protected methods, and I was wondering how one would engage them in the context of a state_machine implementation.. 我非常相信私有和受保护的方法,我想知道如何在state_machine实现的上下文中使用它们。

I'm assuming you're talking about this state_machine . 我假设你在谈论这个state_machine

You can easily make your event transition methods private by marking them as so after their definition, eg 您可以通过在定义之后将它们标记为私有来轻松地将事件转换方法设为私有,例如

class Payment
  attr_reader :state

  state_machine :state, :initial => :pending do
    event :pay do
      transition [:pending] => :paid
    end
  end

  private :pay # that should do!
end

Even though it answers your question, I highly advise against it. 即使它回答了你的问题,我也非常反对。 Making a method private or protected, only concerns about method visibility, ie what you want to expose in your API. 将方法设为私有或受保护,仅关注方法可见性,即您希望在API中公开的内容。 What you should really be looking for in your case, is a way to control access to a certain feature in a certain moment. 在您的情况下,您真正​​应该寻找的是一种在某个时刻控制对某个功能的访问的方法。 This requirement is highly coupled with your domain logic, and not API. 此要求与您的域逻辑高度耦合,而不是API。

Besides, even if you mark your methods as private, it does not guarantee any security because one can easily bypass this restriction calling the method via send, eg payment.send(:pay) . 此外,即使您将方法标记为私有,也不保证任何安全性,因为人们可以轻松绕过此限制,通过send调用方法,例如payment.send(:pay)

I think a better solution would be to create some sort of policy checker or filter before your transactions to make sure they can be processed, eg 我认为更好的解决方案是在您的交易之前创建某种策略检查或过滤,以确保它们可以被处理,例如

before_transition :pending => :paid, :do => :check_merchant

def check_merchant
  really_paid = ... # logic to check with the merchant
    or raise "Payment haven't been processed yet. Hang on a sec"
end

Hope that helps! 希望有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM