Categories

ActiveRecord, method_missing и stack level too deep

Переопределяя у ActiveRecord модели #method_missing важно помнить, что методы чтения атрибутов генерятся через сам #method_missing

Так, например, код

class Appearance < ActiveRecord::Base
  serialize :prefereneces, HashWithIndifferentAccess

  def method_missing(name, *args)
    preferences[name] || super
  end
end

вывалит Exception SystemStackError: stack level too deep

Обойти это можно, вызвав сначала super и перехватив NoMethodError, а потом его рейзануть обратно если не выполнилось необходимое условие.

def method_missing(name, *args)
  super
rescue NoMethodError
  preferences[name] || raise
end

3 comments to ActiveRecord, method_missing и stack level too deep

  • mholub

    Не знал, что в activerecord так набыдлокодили. Интересно, а что мешает просто тупо залезть в базу, посмотреть на все атрибуты и для каждого сделать define_method вместо того, чтобы портить method_missing?

  • mholub

    единственное объяснение, что я придумал – отложенная инициализация, чтобы неиспользуемые атрибуты до поры-до времени не ели память зазря. Но оно мне кажется маловероятным.

  • pahanix

    В проекте я, скорее всего, буду генерить методы доступа к данным, потому как у меня в базе всего одно поле preferences, в которое сериализуются все “атрибуты”, которые, в свою очередь, известны только на момент рантайма и берутся из конфигурационных файлов и могут быть любыми.

    Тут я хотел показать идею.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>