ruby, как иметь два необязательных аргумента, но нужен хотя бы один подарок? - PullRequest
2 голосов
/ 10 мая 2011

У меня есть этот метод, #upload, который в основном принимает, помимо прочих аргументов, опцию файла или некоторый текст.Если файл (File.open ("test.txt", 'r +')) передан, загружен (: file => ...), тогда этот метод читает файл из текста или, если кто-то решит передатьтот же самый текст, только не в текстовом файле, он может сделать загрузку (: content => ...)

Но мне нужен либо файл с текстом, либо сам текст пропущен, как бы вы подошли к этому?

Вот что у меня пока есть.

 def upload(args)
   if args[:content].present?
     self.content = args[:content]
   elsif args[:file].present?
     self.content = args[:file].read
   end
 end

спасибо!

Ответы [ 3 ]

2 голосов
/ 10 мая 2011

Вы специально хотите передать аргумент как хеш? Если нет, я бы пошел на что-то вроде:

def upload(args)
  if args.respond_to? :read
    self.content = args.read
  else
    self.content = args.to_s # This allows non-string arguments.
  end
end
2 голосов
/ 10 мая 2011

Решение 1

Если класс аргумента отличается (String от File), то вы можете использовать его в конструкции case.Вам не нужна дополнительная информация, чтобы различать это.

def upload(arg)
  self.content =
  case arg
  when String; arg
  when File; arg.read
  end
end

Решение 2

Добавлено после того, как вдохновлено комментарием Nemo157

Используя полиморфизм объектно-ориентированного программирования, вы можете сделать это:

def upload(arg); self.content = arg.upload end
class String
  def upload; self end
end
class File
  def upload; read end
end

Некоторые заметки о полиморфизме

Часто мы ссылаемся на похожие, но разные действия водно и то же словоНапример, рассмотрим слово add в контексте обычной жизни: мы используем его в разных значениях: добавляем воду в банку, добавляем 3 к 1, добавляем комментарий, добавляем оттенок синего к зеленой краске и т. Д.,Они имеют разные значения, но у нас есть интуиция, что они как-то связаны.Один из способов различать эти значения будет состоять в том, чтобы использовать разные слова, например, «добавить жидкость», «добавить число», «добавить контекст» или «нумеровать», например, добавить1, добавить2, добавить3, но это беспорядок.Тем не менее, обратите внимание, что их значение в значительной степени зависит от типа объекта, к которому он относится: в зависимости от того, является ли он жидким, числом, дискурсом и т. Д., При этом определяется соответствующий смысл «добавления».Идея полиморфизма использует этот факт и применяет его к программированию.В данном случае «выгрузка» будет иметь разное значение в зависимости от того, идет ли речь о строке или файле.Но пока они определены в их соответствующем классе, вам не нужно заботиться о разнице в их использовании.Следовательно, вы освобождаетесь от оператора case и упрощаете код.

0 голосов
/ 10 мая 2011

Просто сделайте это тестом в методе, что-то вроде

def upload(args)
  if args[:content].present?
    self.content = args[:content]
  elsif args[:file].present?
    self.content = args[:file].read
  else
    raise ArgumentError, 'one of :content or :file must be given'
  end
end

РЕДАКТИРОВАТЬ: альтернатива, которая использует только один аргумент и вводить утку

def upload(arg)
  if arg.respond_to? :to_str
    self.content = arg.to_str
  elsif arg.respond_to? :read
    self.content = arg.read
  else
    raise ArgumentError, 'a String-like or IO-like object must be given'
  end
end

Аналогично двум другим, но я чувствую, что есть пара улучшений

  • Утиная типизация вместо того, чтобы основывать поведение на классе, это означает, что могут использоваться другие классы, если они реализуют правильные методы. В основном это позволяет использовать другие формы ввода-вывода, кроме обычных файлов. Может быть сделано с подтипом, но это не так уж и много в Ruby.

  • Используя to_str вместо to_s, у каждого класса есть метод to_s, и я предполагаю, что вы не хотите загружать контент, такой как #<MyClass:0x523e>. to_str, с другой стороны, реализуется только классами, которые специально должны быть преобразованы в строку.

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