Сервисный объект Rails возвращает "Ошибка метода отсутствует"

Для начала: это моя первая попытка вывести бизнес-логику из пространства модели / контроллера. Вот некоторая начальная логика, которую я пытаюсь абстрагировать. Путь app/services/Date_calc.rb,

class Date_calc
  require User
  require Report

  def months(range)
    User.first.reports.order("report_month desc").limit(range).pluck(:report_month)
  end
end

В моем приложении у меня есть две модели, Пользователь и Отчеты. Пользователь has_many Отчеты. reports таблица имеет поле с именем report_month,

призвание Date_calc.months(6) в консоли Rails возвращается: TypeError: no implicit conversion of Class into String,

Мой предполагаемый ответ был массив дат, например ["01/01/2013", "01/02/2013", "01/03/2013", ... ],

Я не совсем уверен, что я делаю здесь не так.

2 ответа

Решение

В дополнение к обязательным строкам без кавычек вы вызываете метод экземпляра для класса. Вам либо нужно создать экземпляр Date_calc следующим образом

months = Date_calc.new.months(6)

или сделать это методом класса, как это

def self.months(range)...

Проблема в том, что require ожидает строку (например, require "path_to_module") но вы даете ему класс:

require User
require Report

Если это работает в Rails, то Rails автоматически загрузит оба этих класса. Вам не нужно делать require совсем.

Изменить: после того, как вы удалили эти строки, Date_calc.months(6) все еще собирается дать вам NoMethodError, потому что months это метод экземпляра, но вы пытаетесь вызвать его, как если бы это был метод класса. Вам либо нужно вызвать его для экземпляра класса Date_calc, например так:

Date_calc.new.months(6)

Кроме того, вы можете определить его как метод класса, выполнив def self.months(range) вместо def months(range), который позволит вам позвонить Date_calc.months(6), Но вы можете подумать, действительно ли Date_calc должен быть классом, или это должен быть модуль.

Это должен быть класс, если вы хотите иметь несколько его экземпляров, как если бы вы хотели экземпляр пользователя или экземпляр отчета. "Пользователь" и "Отчет" оба являются существительными, потому что класс представляет собой вещь, которую мы могли бы хотеть иметь более чем одним. Имеет ли смысл предложение "Я хочу создать Date_calc"? Как насчет предложения "Я хочу создать два Date_calcs"? Если вы сказали "да" обоим, тогда класс имеет смысл.

Если, однако, вы просто хотите, чтобы что-то добавляло некоторые связанные методы, но это ничего не значит, вы можете вместо этого использовать модуль. В Rails, например, Rails Объект не класс, это модуль. Нет смысла говорить "я хочу создать Rails", а тем более "я хочу создать два Rails". Rails - это просто модуль, используемый для группировки связанных методов. Если Date_calc подходит под это описание, то он имеет больше смысла как модуль:

module Date_calc
  def self.months(range)
    # ...
  end
end

# and then...
Date_calc.months(6)

Как видите, мы используем def self.months вместо def months потому что мы хотим иметь возможность вызывать метод самого модуля.

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