我的问题与此问题非常相似: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
答案 0 :(得分:3)
我会在warden.rb
目录中创建一个名为initializers
的文件,并将猴子补丁代码放在文件中。我经常在我的项目中使用这种技术修补宝石。
要将补丁放在lib目录下,请执行以下操作:
config.autoload_paths += ["#{config.root}/lib/warden"]
PS:我知道你已经尝试了这个,但看起来你的路径不正确。
PPS 要了解Rails 2.3加载序列,请参阅this code。
答案 1 :(得分:-1)