Rails: вызов модельного класса в библиотеке - PullRequest
2 голосов
/ 28 ноября 2008

Я пытаюсь проверить, что параметр является экземпляром определенного класса в Rails:

def schedule(action, *args)
  if arg.is_a? Aircraft
    ...
  end
end

Я делаю это в классе библиотеки (файл находится в lib / ), и я получаю неинициализированную константу Aircraft . Самолеты относятся к классу моделей и имеют соответствующий файл aircraft.rb в app / models .

Можно ли использовать классы моделей и экземпляры в библиотеке? Как?


Контекст ошибки:

Ошибка возникает в тестах RSpec; код работает в браузере. Я пытался запросить модель в файле _spec.rb , но пока безуспешно.

Ответы [ 4 ]

4 голосов
/ 28 ноября 2008

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

Так что нам нужно немного больше контекста, чтобы выяснить, почему он не работает для вас. Возможно ли, что вы загружаете файл lib / без среды Rails?

Одним из способов решения этой проблемы было бы явное требование файла модели aircraft.rb. Тем не менее, вы обнаружите, что этот подход быстро приводит к безумию, так как он сломает автоматический загрузчик Rails тонкими и удивительными способами. Rails намного проще, если вы работаете с загрузчиком классов Rails, а не против него.

Обновление

Так что, если он проходит тест RSpec, можем ли мы увидеть код, который вы используете для загрузки среды, в файле спецификации? Это должно выглядеть примерно так:

require File.dirname(__FILE__) + '/../spec_helper'

и оно должно быть вверху файла. Это предполагает, что у вас установлен плагин RSpec Rails ( здесь ) и что у вас есть файл spec / spec_helper.rb по умолчанию из плагина RSpec. Если такого файла нет, попробуйте выполнить:

ruby script/generate rspec
3 голосов
/ 28 ноября 2008

Это даст вам доступ к модели самолета:

require File.dirname(__FILE__) + "/../app/models/aircraft"

[править]

Даниил хорошо говорит о контексте. Если вы используете задачу rake, убедитесь, что вы загружаете среду:

task :my_task => :environment do
  # something happens...
end 
1 голос
/ 23 февраля 2011

Ответ Даниэля верен, но подумайте: почему класс библиотеки относится к классу модели? Библиотечный код не должен знать о реальных классах моделей, хотя он может знать об интерфейсе, который они предоставляют.

Еще одно соображение: почему метод #schedule запрашивает класс модели? Если бы новый класс модели Spaceship хотел работать с #schedule, то #schedule пришлось бы изменить, чтобы работать с ним. Это не обязательно.

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

Например, что было:

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.

0 голосов
/ 15 февраля 2011

Должен попробовать это: if arg.is_a? ::Aircraft?

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