3

スクリプトの先頭で変数を定義し、それをメソッドで参照したい状況があります。

#############
# Variables #
#############
tmp_dir = '/path/to/tmp/dir'

###########
# Methods #
###########
def cache(page)
  begin
    %x[wget -q -O #{tmp_dir}/page #{page}]
  rescue => msg
    puts "error: #{msg}"
    exit
  end
 end

cache("http://somepage.com")

このエラーが発生しています:

undefined local variable or method `tmp_dir' for main:Object

tmp_dirグローバル変数を作成する必要があると思いますか?グローバル変数を使うのは嫌いです。これを行うRuby風の方法はありますか?

4

5 に答える 5

5

tmp_dirクラス定義では変数として定義されていますが、インスタンス関数では、クラスのインスタンスtmp_dirで定義されたを探しています。そのため、関数内では未定義です。tmp_dir

グローバルにするか、クイックフィックスとしてクラス変数にすることができます。より良い代替手段があると思います:これをキャッシュする方法を知っている独自のクラスにラップし、tmp_dirグローバルまたはクラス変数にせずに初期化します。

class Cacher
    def initialize(tmp_dir)
        @tmp_dir = tmp_dir
    end

    def cache(page)
        wget "#{@tmp_dir}/page"
    end
end

# in your main file:
cacher = Cacher.new('/path/to/tmp/dir') # here's your configuration line, but with no global!

# later

cacher.cache("index.html")
于 2013-07-08T13:48:40.437 に答える
3

あなたが正しいです。グローバル変数は避けるべきです。自然な選択は、クラスのインスタンス変数または定数です。

あなたの場合、スクリプトの実行中に変更されないものがあるようです。その場合、定数が最適です。この定数は、適切なモジュール内で定義できます。

TmpDir = "/path/to/tmp/dir"

また、Ruby には tmp dir を参照する方法が組み込まれていることにも注意してください。

require "tmpdir"
Dir.tmpdir # => "/tmp" (depending on the environment)
于 2013-07-08T13:55:35.080 に答える
0

簡潔な答え

短いスクリプトを書いているようですね。その場合、 のような変更可能なグローバル変数を使用できない理由はありません$tmp_dir。ただし、変更する必要がない場合は、@sawa のようなグローバル定数のソリューションを使用する必要がありますTMP_DIR。その場合.freeze、偶発的な変更を避けるために文字列を呼び出す必要があります。

より長い答え

スクリプトが長くなったり複雑になったりした場合は、クラスにリファクタリングする必要があります。このTMP_DIR場合、ソリューションは引き続き機能します。ただし、値を変更する必要がある場合は、ConfigObjectこれらの変数をグループ化するクラスを作成できます。

例:

ConfigObject = Struct.new(:tmp_dir, :file_limit)
# it's a good idea to create this before everything else
$config = ConfigObject.new('/tmp/dir', 10)

class Foo
  def do_something
    $config.file_limit  # use this somehow
    $config.file_limit = 5  # change
  end
end

同様の手法では、クラス変数を使用して同じことを実現します。

class ConfigObject
  class << self
    attr_accessor :tmp_dir, :file_limit
  end
  @tmp_dir = '/tmp/dir'
  @file_limit = 10
end

class Foo
  def do_something
    ConfigObject.file_limit  # use this somehow
    ConfigObject.file_limit = 5  # change
  end
end

ConfigObject他のクラスで使用される「サービス」と考えてください。アプリが複雑になり、複数の相互作用するサービスが必要になる場合は、サービスへの参照を保持する一種のサービス レジストリを設定する必要がある場合があります (詳細については、Google の「依存性注入」を参照してください)。

Config注:既に組み込みクラスであるため、クラスに名前を付けないでください。

于 2013-07-08T16:31:43.127 に答える