Мой вопрос очень похож на этот: Как добавить метод в рубиновый драгоценный камень без редактирования источника драгоценного камня? .Однако этому вопросу уже почти год, и решение, которое было выбрано, не самое чистое, по крайней мере мне.
Человек, предоставивший ответ, предложил 3 предложения.Первое предложение было выбрано в качестве ответа, но мне бы очень хотелось выяснить, как это сделать вторым способом.
Мне нужно переопределить метод экземпляра класса, который определяется Gem.Более конкретно, это класс SessionSerializer в 1.1.2 Devise .Проблема в том, что Devise не уважает нестандартные имена первичных ключей.Он всегда использует id
.Вы можете видеть, что в warden_compat.rb в строке 30 используется следующее для поиска модели по ее идентификатору:
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.Поэтому у меня есть пара вопросов, на которые, я надеюсь, можно ответить:
Вопросы
- Что я здесь не так делаю?
- Загружает ли Rails файлы определенных путейв
config.autoload_paths
до Gems или наоборот?
Заранее спасибо за помощь!
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