Rails3:HOWTO覆盖/重新打开Gem中的类和Rails初始化过程

问题描述 投票:2回答:2

我的问题非常类似于这个问题:How do I add a method to a ruby gem without editing the gem source?。然而,这个问题已经差不多一年了,所选择的解决方案并不是最干净的,至少对我来说不是。

提供答案的人提出了3条建议。选择第一个建议作为答案,但我真的想弄清楚如何以第二种方式做到这一点。

我需要覆盖由Gem定义的类的实例方法。更具体地说,它是SessionSerializer class in 1.1.2 Devise。问题是Devise不尊重非标准主键名称。它总是使用id。您可以在warden_compat.rb on Line 30中看到它使用以下内容通过它的ID查找模型:

klass.constantize.find(:first, :conditions => { :id => id })

就我而言,我的id专栏的名称是application_user_id,所以很明显这不起作用。 Devise已经在1.1.3中解决了这个问题,但是,我不能使用1.1.3,因为Devise LDAP Authenticatable插件不支持1.1.3。

所以这就是我所做的。我首先应该提一下,我通过直接编辑Gem源来测试这个修复,所以现在我只想将它移动到我的项目中。

  1. session_serializer.rb(即lib/warden/)创建了一个lib/warden/session_serializer.rb文件,重新打开了Warden::SessionSerializer类,并重新定义了deserialize方法。
  2. 修改application.rblib/包括config.autoload_paths config.autoload_paths += ["#{config.root}/lib"]

但是,这似乎没有办法。它仍然使用Gem源中定义的相同代码。所以我有几个问题希望可以回答:

问题

  1. 我在这做错了什么?
  2. Rails是否在Gems之前加载config.autoload_paths中定义的路径文件,还是反过来?

我在这里先向您的帮助表示感谢!

LIB /区长/ session_serializer.rb

module Warden

  class SessionSerializer
    def deserialize(keys)
      klass, id = keys

      if klass.is_a?(Class)
        raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
          "you can fix it by changing one character in your cookie secret, forcing all previous " <<
          "cookies to expire, or cleaning up your database sessions if you are using a db store."
      end
      # NOTE: Original line code. Notice that it uses an :id symbol. It doesn't respect the primary key that explicity defined in the model
      # klass.constantize.find(:first, :conditions => { :id => id })
      # NOTE: THIS IS THE FIX
      klass.constantize.find(:first, :conditions => { :application_user_id => id })
    rescue NameError => e
      if e.message =~ /uninitialized constant/
        Rails.logger.debug "Trying to deserialize invalid class #{klass}"
        nil
      else
        raise
      end
    end
  end

end
ruby-on-rails ruby ruby-on-rails-3 override
2个回答
3
投票

我将在warden.rb目录中创建一个名为initializers的文件,并将猴子补丁代码放入文件中。我经常在我的项目中使用这种技术来修补宝石。

要将修补程序放在lib目录下,请执行以下操作:

config.autoload_paths += ["#{config.root}/lib/warden"]

PS:我知道你试过这个,但看起来你的路径不正确。

PPS要了解Rails 2.3加载序列,请参阅this code


-1
投票
© www.soinside.com 2019 - 2024. All rights reserved.