Grettings!
In приложение, которое безупречно работало в Rails 2.3.8, у меня есть следующий метод класса:
def self.encode(*attr_names)
encoder = Encoder.new(attr_names)
before_save encoder
after_save encoder
after_find encoder
define_method(:after_find) { } # defining here, since there's only alias in the Encoder class itself
end
Этот метод ссылается на класс Encoder. Вот оно:
class Encoder
include Encodings
def initialize(attrs_to_manage) # We're passed a list of attributes that should be stored encoded in the database
@attrs_to_manage = attrs_to_manage
end
def before_save(model) # Before saving or updating, encode the attributes to their original encoding
@attrs_to_manage.each do |field|
model[field] = to_orig_encod(model[field])
end
end
def after_save(model) # After saving, encode them back to utf8
@attrs_to_manage.each do |field|
model[field] = to_utf8(model[field])
end
end
alias_method :after_find, :after_save # Do the same after finding an existing record
end
Перед обновлением до rails3 все обратные вызовы (before_save, after_save, after_find) работали нормально. После обновления before_save и after_save по-прежнему работают, но after_find не работает, и в моем журнале появляется следующее предупреждение об устаревании:
DEPRECATION WARNING: Base#after_find has been deprecated, please use Base.after_find :method instead
I ' Я не знаю, как изменить свой код, чтобы снова включить функцию обратного вызова after_find. Я попробовал несколько простых вариантов, но безуспешно, и документация API rails по этому обратному вызову очень ограничена и без примеров реализации.
Любая помощь приветствуется, заранее спасибо!
Изменить:
Вот решение:
Ладно, похоже, проблема была более тонкой, чем казалось изначально. После дополнительного тестирования я обнаружил, что на самом деле, как указал Джеппе, обратный вызов after_find работает независимо от предупреждения об устаревании, метод «to_utf8» на самом деле был успешно вызван и выполнен для атрибутов модели. Причиной того, что результат не соответствовал ожиданиям, был сам метод to_utf8. Он использует рубиновый модуль Iconv для преобразования строк из кодировки, отличной от utf8, например cp1251, в utf. Это было сделано для атрибутов модели, полученной с помощью Active Record из удаленной устаревшей базы данных с кодировкой, отличной от utf. Однако, как оказалось, в отличие от предыдущих версий rails, AR в rails 3 автоматически и молча выполняет преобразование в ut8 всех объектов, даже тех, которые были получены из БД, не являющихся юникодом. Таким образом, по сути, после обновления мой код закончился повторным преобразованием в строки utf8, которые уже были преобразованы в utf8 с помощью AR, и в результате получилось множество бессмысленных символов. Проблема была решена путем полного удаления обратных вызовов after_find и after_save, так как в этом случае они больше не нужны: )