はじめに、注意
2013年12月19日に facebook に書いていたものをサルベージしてきた投稿です。
その後、後述する main.rb
は進化したみたいですが、Ruby 初心者な私には 1 年前の私のコードをすぐには理解できませんでした。
時間があったら解読して、追加情報として掲載、解説してみたいと思います。
で、ここから
SketchUp で 3D モデルを作っていると、スクリプトでやりたくなるのは必然と思いますが、ある程度のサイズになると適度な粒度でクラスもファイルも分けたくなるわけです。
Ruby Code Editor で実行していると便利は便利なんですが、コードが一つだけのファイルで完結している場合、いくつか問題があります。
-
__FILE__
が使えない(正確には(eval)'
になっている) - ファイルのトップレベルで module を作っても、
AS_RubyEditor::RubyEditor
内の module になってしまう
特に (2) は作ったクラスにアクセスできない現象の原因がわからずかなり嵌りました。
考えてみれば Ruby Code Editor の中でコードを実行した場合、eval するしかないですよね。
でもって、(ここからさきは Ruby についてよく知らないのでわかりませんが、)AS_RubyEditor::RubyEditor
というクラスのコンテキストで eval されている (class_eval
とか?) ので、トップレベルの module が作れないのでしょうね。
ということで、現時点は次のようなプラクティスを採用しています。
まず、必要なスクリプトは一つのディレクトリに集めます。
最初は、Ruby Code Editor で読み込むファイルです。
たとえば start.rb
という名前にします。
load 'c:/Users/takeyuki/Dropbox/3rdpalace/main.rb'
ご覧のとおり、main.rb
という名前のファイルを load するだけですね。
ここではフルパスで load します。
で、main.rb
の内容は次のようになります。
path = __FILE__.split('/')[0..-2].join('/')
$:.include?(path) || $:.push(path)
def mrequire(name)
name = name[/^(\w+)(\.rb)?$/, 1] + '.rb'
load name
end
mrequire '3rdpalace'
__END__
最初の 2 行はスクリプトをまとめたディレクトリをロードパスに追加するコードですね。
start.rb
は __FILE__
が使えないわけですから、この main.rb
で初めてできるわけです。
ディレクトリを移動した場合も start.rb に書いたフルパスだけ修正すればいい、という寸法です。 で、「必要に応じてクラスやモジュールのアンロードができたり、同じファイルを無駄に何度もロードしたりしない」ローダをちゃんと作ろうかと思っていろいろ調べたんですが、
開発段階では毎回毎回(読込みとコンパイルと)評価が行われる load で十分な気がしてきて、そうしちゃいました。
将来的にはどうにかするかもしれないので、mrequire
という関数を作ってみました。
ご覧のとおり、中身はただの load です。 これより、3rdpalace.rb
や、さらにその中から mrequire
されたファイルに修正があれば、単に Ruby Code Editor の「Execute code in SketchUp (Alt + R)」ボタンを押すだけで反映されて実行されるわけです。
厳密に言うと、(モジュールや)クラスのアンロードはしていないので、ファイルに書かれたとおりの新しいクラス定義がそのままメモリ上に上がるのではなく、
すでにメモリ上にロードされたクラスへの追加定義、ということになります。
つまり、メソッドの名前を get_something
から retrieve_something
に変えて再ロードしたとすると、get_something
というメソッドは残ることになります。まあ、ファイル上のクラス定義とメモリ上のクラス定義を完全に同期したい場合は SketchUp を再起動するのが早いでしょう。 てな感じで。
確認環境 : SketchUp Make 12.0.4812 + Ruby Code Editor Version 3.1