2012-11-13 19 views
0

我正在開發我的小新手項目。項目由兩個腳本組成。腳本編號1是從用戶接收參數的命令行界面。腳本編號2創建笛卡爾積,並將其寫入文本文件。我的想法是使所有的工作都不用將任何東西放在一個文件中)。當我嘗試使用 '負載' 我得到這個錯誤:」如何把兩個ruby腳本放到一個工作程序中?

Carthese_product.rb:3:in `<top (required)>': undefined local variable or method 
`x_min' for main:Object (NameError) 
     from D:/Cli_file.rb:25:in `load' 
     from D:/Cli_file.rb:25:in `<main>' 

SCRIPT1(Cli_file.rb):

require 'trollop' 
    opts = Trollop::options do 
    banner <<-EOS 
Welcome to points generator! 

Usage: 
     test [options] <filenames>+ 
where [options] are: 
EOS 
    opt :x_min,    "Minimal value of X", :type => :int 
    opt :x_max,    "Maximal value of X", :type => :int 
    opt :y_min,   "Minimalna wartosc Y", :type => :int 
    opt :y_max,    "Maksymalna wartosc Y", :type => :int 
    opt :interval,   "Interval between points", :type => :int, :default => 1 
    opt :products_file,  "Name of products_file", :type => :string, :default =>  
          "Products"  
    end 

a= opts 
x_min = a[:x_min] 
x_max = a[:x_max] 
y_min = a[:y_min] 
y_max = a[:y_max] 
interval = a[:interval] 
products_file = a[:products_file] 
load 'Carthese_product.rb' 

SCRIPT2(Carthese_product.rb)

products = [] 

(x_min/interval..x_max/interval).each do |x| 
(y_min/interval..y_max/interval).each do|y| 
products << [x*interval,y*interval] 
end 
end 
a = products.map.with_index{|w, i| "#{i+1} #{w[0].to_s} #{w[1].to_s} \n"} 

aFile = File.new(products_file, "w+") 
if aFile 
    a.each{|x| aFile.write(x)} 
else 
puts "Something wrong!" 
end 

我知道最簡單的辦法就是把所有內容放到一個腳本中,但是爲了我的教育目的,我想找另一種方式!感謝您的幫助& intrest!

回答

2

您正試圖使用​​局部變量將數據從一個腳本傳遞到另一個腳本。它不起作用,因爲當在頂層定義時,局部變量具有文件範圍,因此不能從單獨的文件訪問。

您必須爲您的代碼創建適當的接口,以便您可以從其他腳本引用它。創建一個實現了笛卡爾乘積模塊:

# cartesian.rb 

module Cartesian 
    extend self 

    def product(x_range, y_range, interval = 1) 
    [].tap do |products| 
     x_range.step interval do |x| 
     y_range.step interval do |y| 
      products << [x, y] 
     end 
     end 
    end 
    end 
end 

現在,require這個文件在你的命令行應用程序的可執行文件,請在命令行中給出的數據,寫你的輸出:

#/usr/bin/env ruby 
require 'cartesian' 

# Option parsing 

Cartesian.product(x_min..x_max, y_min..y_max, interval).each do |product| 
    puts "(#{product.first}, #{product.last})" 
end 

我建議印刷該程序的輸出到標準輸出流。這樣,如果您想要,可以輕鬆地將輸出重定向到文件:

./cartesian-product $ARGUMENTS > product.list 
0

局部變量不會從一個文件傳播到另一個文件。爲此,您必須在$前加上全局變量。然後您可以運行Cli_file.rb來運行這兩個腳本。

你的腳本現在變成:

Cli_file.rb

require 'trollop' 
opts = Trollop::options do 
banner <<-EOS 
Welcome to points generator! 

Usage: 
    test [options] <filenames>+ 
where [options] are: 
EOS 
    opt :x_min,    "Minimal value of X", :type => :int 
    opt :x_max,    "Maximal value of X", :type => :int 
    opt :y_min,   "Minimalna wartosc Y", :type => :int 
    opt :y_max,    "Maksymalna wartosc Y", :type => :int 
    opt :interval,   "Interval between points", :type => :int, :default => 1 
    opt :products_file,  "Name of products_file", :type => :string, :default =>  
         "Products"  
end 

a= opts 
$x_min = a[:x_min] 
$x_max = a[:x_max] 
$y_min = a[:y_min] 
$y_max = a[:y_max] 
$interval = a[:interval] 
$products_file = a[:products_file] 
load 'Carthese_product.rb' 

Carthese_product.rb

products = [] 

($x_min/$interval..$x_max/$interval).each do |x| 
($y_min/$interval..$y_max/$interval).each do|y| 
products << [x*$interval,y*$interval] 
end 
end 
a = products.map.with_index{|w, i| "#{i+1} #{w[0].to_s} #{w[1].to_s} \n"} 

aFile = File.new($products_file, "w+") 
if aFile 
    a.each{|x| aFile.write(x)} 
else 
    puts "Something wrong!" 
end 

使用全局變量不去做,雖然最好的辦法。所以除非這是一次性的,否則你最好重構你的代碼。

+2

嚴格來說,這是正確的。但是,全局變量並不是一種強有力的方式來傳遞狀態。依賴於全局變量的方法依賴於外部代碼的副作用,而不是依賴於形式化指定和記錄的參數。它們也會不必要地泄露調用代碼不應該關注自己並導致線程問題的數據。對於像這樣的小劇本可能沒問題,但請不要鼓勵人們養成壞習慣。 –

+0

我意識到這一點,但由於您已經提供了更好的方法,OP可以選擇他想要的任何一個。 – rohit89