9

私はルビーとレールが初めてです。含めたすべての gem が、コード内でその関数を直接使用できることがわかりました。コードのインポートも、関数の名前空間もありません。宝石に同じ名前の関数が含まれている場合、これは競合のレシピではありませんか?

そう -

ruby/rails はどのように関数をインポートし、どのように関数を gem にマップしますか? 2 つの gem に同じ関数が含まれている場合、競合が発生する可能性はありますか? ruby ライブラリを明示的に使用したい場合、そのコードをインポートするにはどうすればよいですか? ルビーに名前空間はありますか?

4

3 に答える 3

11

ルビー

ruby が 1 つのファイルで宣言された関数を別のファイルにインポートする方法は、require関数を使用することです。load同様のことを達成しますが、一般的な目的のために、require通常はあなたが望むものです(詳細についてはhttp://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/を参照してください)

hello_lib.rb

def say_hello
  puts "hello"
end

# that's right, you can execute code when a library is required,
# so the sky's the limit of what you can do
puts "Hey, I've been required!"

hello_caller.rb

# load the code from `hello_lib.rb` in the same directory
require './hello_lib.rb'

サブディレクトリ/hello_other_caller.rb

# for illustrative purposes, adding the parent directory to the load path
# so that ruby will look there for files I want to require
$: << '..'
require 'hello_lib.rb'
say_hello    

宝石

Gem は Ruby コードのパッケージ、またはライブラリと考えることができます。gem をロードするにはいくつかの方法がありますが、最も一般的な方法は、requireSay you've installed the progressbargem を使用して単純なプログレス バーをターミナルに表示する方法です ( gem install progressbar)

プログレスバー_test.rb

require 'rubygems'
require 'progressbar'

# this also works
# gem 'progressbar', '~> 0.9.2'

pbar = ProgressBar.new("test", 100)
100.times do
  sleep 0.1
  pbar.inc
end
pbar.finish

これが機能する理由は、requirerubygemsのときに、プログレスバー gem を ruby​​ が必要なファイルを探すパスに追加するためです。

レール

Rails は単なる gem の集まりであり、その中には実行可能なスクリプトを提供するものもあります。以前のバージョンでは、上記と同様に、ロードする gem を指定する必要がありました。しかし、現在では、バージョン管理とソース情報とともに、bundlerすべての gem を 1 つの で指定できます。Gemfileその後、Bundler は gem 間の依存関係を解決し、プロジェクトの特定のバージョン管理を に保持しますGemfile.lock。それbundler自体が gem であるため、次のようなコードがよく見られます。

config/application.rb

require 'bundler'
Bundler.require(:default, Rails.env)

このコードは、Gemfile にリストされているすべての依存関係と、現在の Rails env に対応するグループ (例:development) にリストされている依存関係をすべてロードするように Bundler に指示します。

名前空間

はい、いくつかの方法で問題が発生する可能性があります。2 つの gem が同じ名前である可能性がありますが、その場合は ruby​​gems にプッシュすることはできず、すぐにわかります。より微妙な名前空間の問題は、2 つのファイルが次のようなことを行う場合です。

hello1.rb

def hello
  puts "Hi"
end

hello2.rb

def hello
  puts "Hello, there!"
end

hello3.rb

require './hello1'
require './hello2'
hello

ここでは、グローバル名前空間で名前空間の競合が発生した場合に何が起こるかを確認します。2 つのライブラリが同じクラス名で同じメソッドを定義している場合、同様のことが発生する可能性があります (この種のモンキー パッチは、お勧めできませんが、それでも発生します!)。実際には、特に gem を書いている場合のように、モジュールを名前空間コードに使用するという点で適切な規律が使用されている場合は、これにあまり遭遇しませんhello

module Hello
  # not such a good name, but won't conflict with ::Object
  class Object
    def to_s
      puts 'this is a bad idea'
    end
  end
end
于 2012-08-01T16:25:45.350 に答える
0

Gem はネームスペースなので、明示的にメソッドを呼び出すことができます。

ModuleName::Class

含まれているクラスを明示的に呼び出さない場合、Ruby は呼び出したクラスが見つかるまですべてのクラスを移動し、見つからない場合は NoMethod エラーをスローします。

Ruby がライブラリを表示するには、それが必要です。

require 'some_library'

ライブラリをクラスに含めるには、次のようにします。

class SomeClass
 include SomeLibrary
 ...
于 2012-08-01T16:04:27.947 に答える