Альтернативы обезьяне, исправляющей базовые классы

Мне удается решить это, используя цикл while.

for (let appUrl of appUrls) {
    var count = i++;

    while(true){
        try{

            await page.goto(appUrl);

            const appName = await page.$eval('div.det-name-int', div => div.innerText.trim());

            console.log('\n' + count);
            console.log('Name: ' , appName);

            break;

            } catch(e){
              console.log('\n' + count);
              console.log('ERROR');
              await page.reload(appUrl);

              continue;
            }

}
9
задан Mechanical snail 13 September 2012 в 00:32
поделиться

4 ответа

Любым другим способом сделать это просто был бы более неловкий синтаксис для исправления обезьяны. Существуют способы включить send и eval и все виды вещей, но почему? Идите вперед и сделайте это очевидный путь.

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

Одна альтернатива в Ruby - то, что можно добавить методы к отдельному объекту.

a = "Hello"
b = "Goodbye"
class <<a
  def to_slang
    "yo"
  end
end
a.to_slang # => "yo"
b.to_slang # NoMethodError: undefined method `to_slang' for "Goodbye":String
15
ответ дан 4 December 2019 в 08:34
поделиться

Если Вы хотите добавить новый метод, который доступен для каждого строкового объекта, то, делая его способ, которым у Вас есть он, состоит в том, как сделать его.

Хорошая практика должна поместить Ваши расширения базовых объектов в отдельном файле (как string_ex.rb) или подкаталог (как extensions или core_ext). Таким образом, очевидно, что было расширено, и для кого-то легко видеть, как они были расширены или изменены.

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

6
ответ дан 4 December 2019 в 08:34
поделиться

Спасибо, ребята.

Вся предложенная работа реализации. Что еще более важно, я учился весить в случае в руке и решать при повторном открытии ядра (или библиотека), классы являются хорошей идеей или нет.

FWIW, друг, на которого указывают send реализация я искал. Но теперь, когда я смотрю на него, это еще ближе к monkeypatching, чем все другие реализации :)

module M
    def do_magic
    ....
    end
end
String.send(:include, M)
1
ответ дан 4 December 2019 в 08:34
поделиться

object класс определяет send, и все объекты наследовали это. Вы "отправляете" объект send метод. send параметры метода являются именем method-you-want-to-invoke как символом, сопровождаемым любыми аргументами и дополнительным блоком. Можно также использовать __send__.

>> "heya".send :reverse
=> "ayeh"

>> space = %w( moon star sun galaxy )
>> space.send(:collect) { |el| el.send :upcase! }
=> ["MOON", "STAR", "SUN", "GALAXY"]

Править..

Вы, вероятно, хотите использовать define_method метод:

String.class_eval {
  define_method :hello do |name|
    self.gsub(/(\w+)/,'hello') + " #{name}"
  end
}

puts "Once upon a time".hello("Dylan")
# >> hello hello hello hello Dylan

Это добавляет методы экземпляра. Добавить методы класса:

eigenclass = class << String; self; end
eigenclass.class_eval {
  define_method :hello do
    "hello"
  end
}

puts String.hello
# >> hello

Вы не можете определить методы, которые ожидают блок все же.

Это могла бы быть хорошая вещь иметь чтение этой главы из того, Почему Острое Руководство, Вы, может пропустить вниз к Массиву "Dwemthy" для получения до материала метапрограммирования.

2
ответ дан 4 December 2019 в 08:34
поделиться