0

情况如下:

我有一个用户模型和两个用于身份验证的模块:Oauth 和 Openid。它们都覆盖ActiveRecord#save,并且有相当多的实现逻辑。

鉴于我可以判断用户何时尝试通过 Oauth 与 Openid 登录,但它们都已被覆盖save,那么“最终”如何覆盖save以便我可以有条件地调用其中一个模块的实现?

这是我所描述的基本结构:

module UsesOauth

  def self.included(base)
    base.class_eval do
      def save
        puts "Saving with Oauth!"
      end

      def save_with_oauth
        save
      end
    end
  end

end

module UsesOpenid

  def self.included(base)
    base.class_eval do
      def save
        puts "Saving with OpenID!"
      end

      def save_with_openid
        save
      end
    end
  end

end

module Sequencer

  def save
    if using_oauth?
      save_with_oauth
    elsif using_openid?
      save_with_openid
    else
      super
    end
  end

end

class User < ActiveRecord::Base
  include UsesOauth
  include UsesOpenid
  include Sequencer
end

我正在考虑使用alias_methodlike so,但这太复杂了,因为我可能还有 1 或 2 个类似的模块。我也尝试使用这些save_with_oauth方法(如上所示),几乎可以工作。唯一缺少的是我还需要调用ActiveRecord::Base#save(超级方法),所以是这样的:

def save_with_oauth
  # do this and that
  super.save
  # the rest
end

但我不允许在 ruby​​ 中这样做。

有什么聪明的解决方案的想法吗?

alias_method_chain会做吗?我避免这样做,因为人们似乎说这是一个坏主意。

(边走边找东西):

4

1 回答 1

2

是的,别名方法链会在这种情况下为您提供帮助。

但考虑使用委托模式。原始的保存方法会触发特殊委托对象的回调(也可以是 nil),它会在保存用户时执行任何需要做的事情。

还有一个类似的模式直接被称为观察者的 actve 记录支持,尝试阅读一些关于它的东西也许这也是一个很好的解决方案。

我并不是说这种链接方法是错误的,但是有更简洁的方法可以实现您想要的。

于 2010-05-10T08:45:38.970 回答