Лучший способ организовать длинный кусок кода в блоке уточнения ruby

module Access
  def last
    self[-1]
  end

  def start_end
    self[0] + last
  end
end

module StringExt
  refine String do
    include Access
  end
end

using StringExt

puts 'abcd'.last       # => d
puts 'abcd'.start_end

Когда класс очищается с помощью слишком большого количества связанных методов, я думаю, что лучше извлечь их в модуль. Тем не менее, в приведенном выше примере, который демонстрирует проблему, когда один метод вызывает другой (см. Последний оператор), и он выдает следующую ошибку.

в 'start_end': неопределенная локальная переменная или метод 'last' для "abcd":String (NameError)

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

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

1 ответ

Решение

Вот общий шаблон, который я в итоге использовал. По сути, я не нашел обходного пути для использования глобальных идентификаторов на каком-то уровне. Но это может быть сделано довольно чисто, создавая эти глобальные классы / модули. Это будет более понятно в качестве примера:

module StringPatches

  def self.non_empty?(string)
    !string.empty?
  end

  def non_empty?
    StringPatches.non_empty?(self)
  end

  def non_non_empty?
    !StringPatches.non_empty?(self)
  end

  refine String do
    include StringPatches
  end

end

class Foo
  using StringPatches
  puts "asd".non_empty? # => true
  puts "asd".non_non_empty? # => false
end

Методы класса на StringPatches не экспортируется в using, Но поскольку классы / модули являются константами (глобальными переменными), к ним можно получить доступ откуда угодно.

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