【发布时间】:2010-11-05 16:22:11
【问题描述】:
我的问题与这个问题非常相似: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 源代码来测试此修复,所以现在我只想将它移到我的项目中。
- 在
lib/warden/(即lib/warden/session_serializer.rb)中创建session_serializer.rb文件,重新打开Warden::SessionSerializer类,并重新定义deserialize方法。 -
修改了
application.rb以在config.autoload_paths中包含lib/config.autoload_paths += ["#{config.root}/lib"]
但是,这似乎并不能解决问题。它仍在使用 Gem 源代码中定义的相同代码。所以我有几个问题希望能得到解答:
问题
- 我在这里做错了什么?
- Rails 是在 Gems 之前加载
config.autoload_paths中定义的路径的文件,还是相反?
提前感谢您的帮助!
lib/warden/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 overriding