Catch-22: Rails перенос db не запускается, когда константы класса делают вызовы db - PullRequest
0 голосов
/ 04 августа 2009

У меня есть класс, подобный следующему:

class FruitKinds < ActiveRecord::Base
  Apple = FruitKinds.find(:all).find { |fk|
    fk.fruit_name == :apple.to_s
  }

  # ... other fruits

  # no methods
end

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

Однако есть проблема. Существует миграция базы данных для создания таблицы FruitKinds и заполнения ее специальным Fruits, например Apple. Когда выполняется миграция базы данных для инициализации FruitKinds, rake не запускается, потому что сначала загружается FruitKinds, который затем вызывает базу данных, что, конечно же, завершается неудачей, поскольку таблицы FruitKinds еще нет.

Обходной путь - закомментировать поля FruitKinds :: * во время миграции, но это ужасно и хакерски. Какой лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 04 августа 2009

Это довольно распространенная ошибка, и теперь я считаю любой доступ к базе данных на уровне определения класса антипаттерном. Альтернатива состоит в том, чтобы сделать это ленивым свойством. Самый простой способ сделать это - просто сделать метод уровня класса вместо константы. Обратите внимание, что вы можете использовать заглавные методы в Ruby, поэтому вы можете сделать так, чтобы они выглядели как константа, если хотите:

class FruitKinds < ActiveRecord::Base
  def self.Apple 
    @apple ||= FruitKinds.find(:all).find { |fk|
      fk.fruit_name == :apple.to_s
    }
  end

  # ... other fruits

  # no methods
end

Или, если вы хотите получить фантазию, вы можете использовать const_missing для динамического создания константы при первом обращении к ней.

Как примечание, это самый неэффективный способ найти запись по имени; -)

0 голосов
/ 04 августа 2009

Как уже упоминал Авди, вам следует избегать взаимодействия с базой данных при загрузке класса. Если вы хотите кэшировать записи базы данных в локальной памяти, я рекомендую использовать функцию Memoization, добавленную в Rails 2.2. Подробнее см. Мой пост здесь .

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