Я пытаюсь проверить, является ли параметр экземпляром определенного класса в Rails:
def schedule(action, *args)
if arg.is_a? Aircraft
...
end
end
Я делаю это в классе библиотеки (файл находится в lib /) и получаю ошибку неинициализированная константа Aircraft. Самолет - это класс модели с соответствующим файлом aircraft.rb в приложение / модели.
Могу ли я использовать классы и экземпляры моделей в библиотеке? Как?
Контекст ошибки:
Ошибка возникает в тестах RSpec; код работает в браузере. Я попытался запросить модель в файле _spec.rb, на данный момент безуспешно.





Это даст вам доступ к модели самолета:
require File.dirname(__FILE__) + "/../app/models/aircraft"
[редактировать]
Дэниел хорошо подходит к контексту. Если вы используете задачу с граблями, убедитесь, что вы загружаете среду:
task :my_task => :environment do
# something happens...
end
Вы можете использовать классы моделей в файлах библиотеки Rails, и вы делаете это правильно. Rails должен автоматически загружать класс Aircraft при обращении к нему.
Поэтому нам нужно немного больше контекста, чтобы понять, почему у вас не получается. Возможно ли, что вы загружаете lib / file без среды Rails?
Один из способов решить эту проблему - явно потребовать файл модели aircraft.rb. Однако вы обнаружите, что такой подход быстро приводит к безумию, поскольку он удивительным образом ломает автозагрузчик Rails. Rails намного проще, если вы работаете с загрузчиком классов Rails, а не против него.
Обновлять
Итак, если это тест RSpec, можем ли мы увидеть код, который вы используете для загрузки среды в файле спецификации? Это должно выглядеть примерно так:
require File.dirname(__FILE__) + '/../spec_helper'
и он должен быть вверху файла. Предполагается, что у вас установлен плагин RSpec Rails (здесь) и что у вас есть файл spec / spec_helper.rb по умолчанию из плагина RSpec. Если такого файла нет, попробуйте запустить:
ruby script/generate rspec
Приходилось пробовать это:
if arg.is_a? ::Aircraft?
Ответ Даниэля правильный, но подумайте: почему класс библиотеки относится к классу модели? Код библиотеки не должен знать о реальных классах модели, хотя может знать об интерфейсе, который они предоставляют.
Еще одно соображение: почему метод #schedule запрашивает класс модели? Если новый класс модели, Spaceship, хотел бы работать с #schedule, то #schedule пришлось бы изменить для работы с ним. В этом нет необходимости.
Вместо этого, чем отличается способ, которым объект Aircraft и объекты других классов обрабатываются #schedule? Можете ли вы выделить это различие отдельным методом? Затем вы можете переместить эти реализации в каждый из классов модели и решить, какая из них используется полиморфизмом, а не ветвлением.
Например, что раньше было:
def schedule(action, vehicle)
if vehicle.is_an?(Aircraft)
possible_days = case action
when "travel"
["Mon", "Wed", "Fri"]
when "repair"
["Sat", "Sun"]
end
possible_days.rand
elsif vehicle.is_a?(Spaceship)
possible_days = case action
when "travel"
["Sat", "Tue", "Thu"]
when "repair"
["Sun", "Mon"]
end
possible_days.rand
end
end
станет:
def schedule(action, vehicle)
vehicle.days_action_can_be_performed(action).rand
end
class Aircraft
def days_action_can_be_performed(action)
possible_days = case action
when "travel"
["Mon", "Wed", "Fri"]
when "repair"
["Sat", "Sun"]
end
possible_days
end
end
class Spaceship
def days_action_can_be_performed(action)
possible_days = case action
when "travel"
["Sat", "Tue", "Thu"]
when "repair"
["Sun", "Mon"]
end
possible_days
end
end
Когда добавляется новый класс, ему просто нужно реализовать #days_action_can_be_performed, и он будет работать с #schedule.
Ах, спасибо вам большое! Вы указали мне правильное направление: он отлично работает в браузере. Я еще не пробовал, потому что занимаюсь TDD: он ломается в RSpec. Я поправлю вопрос.