我的问题非常类似于这个问题: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源来测试这个修复,所以现在我只想将它移动到我的项目中。
session_serializer.rb
(即lib/warden/
)创建了一个lib/warden/session_serializer.rb
文件,重新打开了Warden::SessionSerializer
类,并重新定义了deserialize
方法。application.rb
在lib/
包括config.autoload_paths
config.autoload_paths += ["#{config.root}/lib"]
但是,这似乎没有办法。它仍然使用Gem源中定义的相同代码。所以我有几个问题希望可以回答:
config.autoload_paths
中定义的路径文件,还是反过来?我在这里先向您的帮助表示感谢!
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
我将在warden.rb
目录中创建一个名为initializers
的文件,并将猴子补丁代码放入文件中。我经常在我的项目中使用这种技术来修补宝石。
要将修补程序放在lib目录下,请执行以下操作:
config.autoload_paths += ["#{config.root}/lib/warden"]
PS:我知道你试过这个,但看起来你的路径不正确。
PPS要了解Rails 2.3加载序列,请参阅this code。