Rails: вызов класса модели в библиотеке

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

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

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

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


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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
5 377
4

Ответы 4

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

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

Ах, спасибо вам большое! Вы указали мне правильное направление: он отлично работает в браузере. Я еще не пробовал, потому что занимаюсь TDD: он ломается в RSpec. Я поправлю вопрос.

Christian Lescuyer 29.11.2008 16:37

Приходилось пробовать это: 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.

Другие вопросы по теме