Рефакторинг response_to? вызовите условие if-elsif-else - PullRequest
2 голосов
/ 20 июля 2010

У меня есть следующий метод, и я хочу сделать его более читабельным:

def value_format(value)
  if value.respond_to? :to_actor
    value.to_actor
  elsif value.respond_to? :to_subject
    value.to_subject
  elsif value.respond_to? :to_json
    value.to_json
  elsif value.respond_to? :to_hash
    value.to_hash
  else
    value.inspect
  end
end

Это мое решение.Что вы думаете?

def value_format(value)
  methods = [:to_actor, :to_subject, :to_json, :to_hash, :inspect]
  value.send(methods.find_all { |m| m if value.respond_to? m }.first)
end

Ответы [ 3 ]

4 голосов
/ 20 июля 2010

Ваше решение выглядит хорошо, но вы также можете использовать find вместо find_all:

METHODS = [:to_actor, :to_subject, :to_json, :to_hash, :inspect]
def value_format(value)
  value.send(METHODS.find { |m| value.respond_to? m })
end

Преимущество использования константы состоит в том, что каждый раз при запуске value_format не создается новый массив.

0 голосов
/ 15 марта 2013

Драгоценный камень Facets обеспечивает элегантное решение (я думаю) этой проблемы.Он объединяет два этапа проверки, отвечает ли объект методу и фактически вызывает этот метод в один шаг.

Таким образом, ваш пример можно переписать так:

require 'facets/kernel/respond'

def value_format(v)
  v.respond.to_actor || v.respond.to_subject || v.respond.to_json || v.respond.to_hash || v.respond.inspect
end

Обратите внимание, чтоэтот метод работает, только если можно с уверенностью предположить, что ни один из этих методов не вернет nil или false (поскольку respond возвращает nil, если объект не отвечает, это то, что позволяет нам связыватьвместе с кучей or s).

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

Документация:

  # Like #respond_to? but returns the result of the call
  # if it does indeed respond.
  #
  #   class RespondExample
  #     def f; "f"; end
  #   end
  #
  #   x = RespondExample.new
  #   x.respond(:f)  #=> "f"
  #   x.respond(:g)  #=> nil
  #
  # or
  #
  #   x.respond.f   #=> "f"
  #   x.respond.g   #=> nil
0 голосов
/ 20 июля 2010

Кажется, в вашем решении довольно простая оптимизация:

def value_format(value)
  methods = [:to_actor, :to_subject, :to_json, :to_hash]
  value.send(methods.find(:inspect) { |m| value.respond_to? m })
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...