Скрипт Ruby запускается из определенной строки или метода


Допустим, у меня есть сценарий:

!#usr/bin/ruby

# step 1
puts "That's first"
# some code

#step 2
puts "That's second"
# some code

Есть ли способ передать ARGV скрипту, который начнет выполнение с определенной строки (или шага, или класса, или чего-то еще)? Например, выполнение $ ruby script.rb -s 2 начнется со второго шага.

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

Есть идеи?

3 4

3 ответа:

Есть способы, как показывает ответ Макса, но вы не должны этого делать. Были вопросы о заявлении Гото для Руби, прежде чем вы узнали. Почему вы должны возвращаться к методам, используемым в BASIC ? Покажите нам использование, и мы покажем вам лучшие способы.

Если вы начинаете с Ruby и программирования, вы можете просто использовать процедурный способ программирования, такой как

def print_a
  puts "a"
end

И позже, независимо от того, где строка "puts a" переместилась между вами последнее обновление

print_a

Если вы более опытные вы будете использовать это с комбинацией объектно-ориентированного или функционального способа программирования.

Мне приходит на ум одно акцептивное употребление: условные require's или load'S

if condition
  require ./mycode_only_to be_executed_in_this_case.rb'
end
Надеюсь, я заставил тебя пересмотреть свой вопрос..

Редактировать после комментария op

Пример, на который вы ссылаетесь, не сухой, это первое, что я замечаю. См. https://en.wikipedia.org/wiki/Don ' t_repeat_yourself для определения сухого

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

require 'watir'

def goto_site site
  a = Watir::Browser.new :chrome
  a.goto site
  # a lot of code down here
  a.close
end

goto_site 'site.com'

Плохие вещи случаются, когда вы используете GOTO.

Вот предложение, которое может решить вашу проблему немного более элегантным способом:

Определите свои шаги в ' define_steps.rb':

# define_steps.rb
#####################################################
@steps = []

def step(i, &block)
  @steps[i] = block
end

def launch_steps!(min = 0, max = @steps.size - 1)
  @steps[min..max].each.with_index(min) do |block, i|
    if block
      puts "Launching step #{i}"
      block.call
    end
  end
end
#####################################################

step 1 do
  puts 'Step 1 with lots of code'
end

step 2 do
  puts 'Step 2 with lots of code'
end

step 3 do
  puts 'Step 3 with lots of code'
end

step 4 do
  puts 'Step 4 with lots of code'
end

Запускайте их отдельно с помощью launch_steps.rb:

# launch_steps.rb
require_relative 'define_steps'

launch_steps!
puts "-----------------"
launch_steps!(2,3)

Выводит :

Launching step 1
Step 1 with lots of code
Launching step 2
Step 2 with lots of code
Launching step 3
Step 3 with lots of code
Launching step 4
Step 4 with lots of code
-----------------
Launching step 2
Step 2 with lots of code
Launching step 3
Step 3 with lots of code

launch_steps! без параметров выполняется каждый определенный шаг, launch_steps!(min,max) выполняется каждый шаг между min и max, launch_steps!(min) бежит Шаг min и каждый шаг после.

Вот программа run_from_line.rb, которая принимает три аргумента: путь, начальная строка и конечная строка. Конечная строка необязательна и по умолчанию равна -1.

#/usr/bin/env ruby

path = ARGV.shift
program_text = File.readlines(path)
start_line = ARGV.shift.to_i;
end_line = ARGV.shift || '-1'
end_line = end_line.to_i

selected_code = program_text[start_line..end_line].join
eval selected_code

С этим скриптом в test.rb:

puts "line 0"
puts "line 1"
puts "line 2"

Тестирование:

> ruby run_from_line.rb test.rb 1
line 1
line 2

> ruby run_from_line.rb test.rb 1 1
line 1

Если вы хотите сделать этот сценарий общесистемным, запустите chmod a+x run_from_line.rb затем sudo mv run_from_line.rb /usr/local/sbin