Просто удалите эти переполнение: автоматический часть и близко внутреннее отделение правильно с закрывающим тэгом, тот путь это работает в IE6, IE7, Firefox 3 и Opera =>, вероятно, все браузеры.
Как насчет того, чтобы рассматривать их все как массивы
? Поведение, которое вы хотите для String
s, такое же, как для Array
, содержащего только эту String
:
def foo(obj, arg)
[*arg].each { |method| obj.send(method) }
end
[* arg]
работает, потому что оператор splat ( *
) превращает отдельный элемент в себя или массив
во встроенный список его элементов.
Позже
Это в основном просто синтаксически улучшенная версия или ответ Арно , хотя есть небольшие различия, если вы передадите Array
, содержащий другие Array
.
Еще позже
Там дополнительная разница, связанная с возвращаемым значением foo
. Если вы вызовете foo (bar,: baz)
, вы можете быть удивлены, если получите обратно [baz]
. Чтобы решить эту проблему, вы можете добавить Kestrel :
def foo(obj, arg)
returning(arg) do |args|
[*args].each { |method| obj.send(method) }
end
end
, который всегда будет возвращать переданный arg
. Или вы можете сделать return (obj)
, чтобы вы могли связать вызовы с foo
. Вам решать, какое поведение возвращаемого значения вы хотите.
Поскольку Array
и String
оба являются Enumerables
, нет элегантного способа сказать «вещь, которая является Enumberable, но не String », по крайней мере, так, как обсуждается.
Я бы сделал тип утки для Enumerable ( Responds_to?: []
), а затем использовал case
, например так:
def foo(obj, arg)
if arg.respond_to?(:[])
case arg
when String then obj.send(arg)
else arg.each { |method_name| obj.send(method_name) }
end
end
end
или даже более чистый:
def foo(obj, arg)
case arg
when String then obj.send(arg)
when Enumerable then arg.each { |method| obj.send(method) }
else nil
end
end
Используйте Marshal для сериализации ваших объектов перед их отправкой.
Допустим, ваша функция называется func
Я бы сделал массив из параметров с помощью
def func(param)
a = Array.new
a << param
a.flatten!
func_array(a)
end
. В итоге вы реализуете свою функцию func_array только для массивов
с помощью func (" привет, мир ") вы получите a.flatten! => ["привет, мир"] с func (["привет", "мир"]) вы получите a.flatten! => ["привет", "мир"]
Если вы не хотите использовать monkeypatch, просто перед отправкой переместите список в соответствующую строку. Если вы не против патчинга обезьян или наследования, но хотите сохранить ту же сигнатуру метода:
class ToBePatched
alias_method :__old_takes_a_string, :takes_a_string
#since the old method wanted only a string, check for a string and call the old method
# otherwise do your business with the map on things that respond to a map.
def takes_a_string( string_or_mappable )
return __old_takes_a_string( string_or_mappable ) if String === string_or_mappable
raise ArgumentError unless string_or_mappable.responds_to?( :map )
# do whatever you wish to do
end
end
Возможно, вопрос был недостаточно ясным, но ночной сон показал мне два чистых пути чтобы ответить на этот вопрос.
1: to_sym
доступен для String
и Symbol
и должен быть доступен для всего, что крякает, как строка.
if arg.respond_to? :to_sym
obj.send(arg, ...)
else
# do array stuff
end
2: отправить throws TypeError
при передаче массива.
begin
obj.send(arg, ...)
rescue TypeError
# do array stuff
end
Мне особенно нравится №2. Я очень сомневаюсь, что кто-либо из пользователей старого API ожидает, что TypeError будет вызван этим методом ...
to_sym
доступен для String
и Symbol
и должен быть доступен для всего, что крякает, как строка.
if arg.respond_to? :to_sym
obj.send(arg, ...)
else
# do array stuff
end
2: send throws TypeError
] при передаче массива.
begin
obj.send(arg, ...)
rescue TypeError
# do array stuff
end
Мне особенно нравится №2. Я очень сомневаюсь, что кто-либо из пользователей старого API ожидает, что TypeError будет вызван этим методом ...
to_sym
доступен для String
и Symbol
и должен быть доступен для всего, что крякает, как строка.
if arg.respond_to? :to_sym
obj.send(arg, ...)
else
# do array stuff
end
2: send throws TypeError
] при передаче массива.
begin
obj.send(arg, ...)
rescue TypeError
# do array stuff
end
Мне особенно нравится №2. Я очень сомневаюсь, что кто-либо из пользователей старого API ожидает, что TypeError будет вызван этим методом ...
Они также возникают время от времени, когда я кодирую. Вы могли бы подумать о переносе второго оператора using в другую функцию?
просто добавьте метод, обрабатывающий параметр типа массива. Это немного другое поведение, поэтому может иметь смысл дополнительный метод.