Как постоянно держать модель загруженной в Rails 3.1 - PullRequest
1 голос
/ 27 августа 2011

Ну, проблема в следующем.У меня есть иерархия моделей следующим образом:

class A < ActiveRecord::Base
end

Class B < A
end

class C1 < B
end

class C2 < B
end

В одном из контроллеров мне нужно искать B, C1 или C2.Rails делает это, если загружены связанные модели.Таким образом, SQL-запрос должен (и в идеале) содержать что-то вроде

B.find 224 
# => SELECT "bs".* FROM "bs" WHERE "bs"."type" IN ('B','C1','C2') AND "bs"."id" = 224 LIMIT 1

И это именно то, что нужно.Однако оказывается, что модели выгружаются при каждом запросе и не загружаются снова (не уверен по причинам этого).В этом случае, если моделей нет в памяти, ActiveRecord выполнит запрос, подобный

B.find 224 
# => SELECT "bs".* FROM "bs" WHERE "bs"."type" IN ('B') AND "bs"."id" = 224 LIMIT 1

Если вы просто вызовете C1 или C2, прежде чем обнаружите, что их типы будут включены в sql

C1
B.find 224 
# => SELECT "bs".* FROM "bs" WHERE "bs"."type" IN ('B','C1') AND "bs"."id" = 224 LIMIT 1

Я пытался загрузить эти модели в инициализаторы.eval C1, требуют 'app / models / c1.rb', require_dependancy 'app / models / c1.rb', но ни одна из этих работ.На самом деле, они все работали на один раз.Только один раз после запуска сервера.Я подозреваю, что не будет такой проблемы в производственной среде, но это очень раздражает.

Уродливое решение состоит в том, чтобы вызывать C1 и C2 после определения B, в этом случае это работало, как ожидалось, но, как я сказалуже, это уродливо

class B < A
end
C1, C2

Есть лучшие идеи?

Обновление перенесено в ответ.

Ответы [ 3 ]

0 голосов
/ 09 декабря 2011

Если вы хотите отключить перезагрузку классов в разработке, вы можете сделать это.В config / environment / development.rb просто сделайте:

config.cache_classes = true

вместо значения по умолчанию false.Это отключит перезагрузку класса режима разработки для всех классов, что довольно неудобно.Теоретически должен быть способ освободить только определенные классы от перезагрузки классов в режиме разработки, но он постоянно меняется от версии rails к версии rails, и часто не работает правильно, и я не отслеживал, как это сделатьэто в текущих рельсах или если это работает.Я не чувствую себя комфортно с вашей хакерской попыткой реализовать эту функцию самостоятельно с помощью патча обезьяны - тот факт, что Rails пытался поддерживать эту официально различными способами в прошлом, но не удалось, означает, что это сложно сделать правильно, и вы, вероятно, ещет.

ОДНАКО.Я не думаю, что это действительно то, что вы ищете.Я думаю, что в вашем общем дизайне есть что-то странное, и отключение перезагрузки класса - это просто обходной путь.Но я не уверен, что именно ты пытаешься сделать или что происходит.ActiveRecord поддерживает иерархию класса модели «наследование одной таблицы», но кажется, что вместо этого вы пытаетесь выполнить «наследование нескольких таблиц».

Я не уверен , если AR поддерживаетнаследование нескольких таблиц или нет - я буду искать документацию по этому вопросу, и если AR поддерживает это, делайте так, как вам говорят - и если AR не поддерживает его, откажитесь от дизайна, если вы действительно не хотитепроникнуть во внутренности AR и выяснить, как заставить AR сделать это, или написать расширение для AR, чтобы сделать это.Тот факт, что это почти работает, может заставить меня догадаться, что AR поддерживает наследование нескольких таблиц, но вам не хватает какой-то конфигурации, чтобы сказать это.

Существует также функция "полиморфной ассоциации" Rails, которая может быть полезной для вас.

В основном, извините, не уверен, что AR может делать то, что вы хотите, но на вашем месте я бы попробовал, только если смогу найти доказательства того, что AR действительно поддерживает это - даже если вы заставляете его работатьотключив перезагрузку класса dev-mode, возможно, вас ждут другие странные ошибки, если вы пытаетесь сделать что-то, что AR не поддерживает.AR сложный код.

0 голосов
/ 05 сентября 2012

Хорошо, думаю, я нашел какое-то решение. Это не очень впечатляет, но, кажется, работает:

Мне требуется добавить хак в ActiveSupport :: Dependencies.

Итак, вот список взлома:

    #lib/system_hacks/active_support.rb
    module ActiveSupport #:nodoc:
      module Dependencies #:nodoc:

        #this array contains all the constants that have to be constantly loaded
        mattr_accessor :constantly_loaded_files
        self.constantly_loaded_files = []

        #redefining the method, with additional line
        def remove_unloadable_constants!
          autoloaded_constants.each { |const| remove_constant const }
          autoloaded_constants.clear
          Reference.clear!
          explicitly_unloadable_constants.each { |const| remove_constant const }
          #a hack
          constantly_loaded
        end

        #will simply make a call for each constants
        #in that case they will be updated... but still in the memory
        def constantly_loaded
          constantly_loaded_files.each do |file|
            file.to_s.classify.constantize
          end
        end
      end
    end

А в инициализаторах небольшой файл для загрузки хака и присвоения массива констант:

  #config/initializers/model_loader.rb
  require File.join(Rails.root, 'lib','system_hacks','active_support')
    module ActiveSupport #:nodoc:
      module Dependencies #:nodoc:
        self.constantly_loaded_files = [A, B, C1, C2]
      end
    end

Если у вас есть какие-либо комментарии, я с удовольствием их выслушаю.

0 голосов
/ 29 ноября 2011

Можете ли вы объяснить, чего пытается достичь эта структура данных? Я вижу шаблон наследования одной таблицы, настроенный в наследовании модели, но я не вижу, какое первоначальное решение вы пытаетесь достичь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...