web-dev-qa-db-ja.com

Rubyメソッドで引数を識別するためにシンボルはどのように使用されますか

私はRailsを学び、Rubyに戻って、Rails(およびRuby本当に機能します)。次のようなメソッド呼び出しが表示された場合:

validates validates :first_name, :presence => true

混乱します。シンボルまたはハッシュを受け入れるRubyでメソッドをどのように記述しますか。validatesメソッドのソースコードも混乱します。誰かがRubyクラスとインスタンスのメソッドは私にとって?

更新:

いいね@Dave!しかし、私が試していたのは次のようなものでした。

def full_name (:first_name, :last_name)
  @first_name = :first_name
  @last_name = :last_name
  p "#{@first_name} #{last_name}"
end

full_name("Breta", "Von Sustern")

これは明らかにエラーを引き起こします。私は理解しようとしています:シンボルが他の値とまったく同じであるのに、なぜこのようなシンボルを引数として渡すのが間違っているのですか?

14
Amit Erandole

シンボルとハッシュは他の値と同じように値であり、他の値タイプと同じように渡すことができます。

ActiveRecordモデルは引数としてハッシュを受け入れることを思い出してください。最終的にはこれに似たものになります(これは単純ではありませんが、最終的には同じ考えです):

class User
  attr_accessor :fname, :lname

  def initialize(args)
    @fname = args[:fname] if args[:fname]
    @lname = args[:lname] if args[:lname]
  end
end

u = User.new(:fname => 'Joe', :lname => 'Hacker')

これは、ハッシュを中括弧に入れる必要がないことを利用しています{}パラメーターを明確にする必要がない限り(そして、パラメーターをスキップするとブロック解析の問題も発生します)。

同様に:

class TestItOut
  attr_accessor :field_name, :validations

  def initialize(field_name, validations)
    @field_name = field_name
    @validations = validations
  end

  def show_validations
    puts "Validating field '#{field_name}' with:"
    validations.each do |type, args|
      puts "  validator '#{type}' with args '#{args}'"
    end
  end
end

t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 })
t.show_validations

この出力:

Validating field 'name' with:
  validator 'presence' with args 'true'
  validator 'length' with args '{min: 2, max: 10}'

そこから、このようなことがどのように機能するかを確認できます。

22
Dave Newton

Ruby 2+の更新を追加すると思いました。これは、「引数としての記号」で最初に見つけた結果だからです。

Ruby 2.0.0なので、メソッドを定義するときにシンボルを使用することもできます。メソッドを呼び出すと、これらのシンボルは他の言語の名前付きオプションパラメータとほぼ同じように機能します。以下の例を参照してください。

def variable_symbol_method(arg, arg_two: "two", arg_three: "three")
  [arg, arg_two, arg_three]
end

result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg"

# result is now equal to:
[:custom_symbol, "two", "Modified symbol arg"]

例に示されているように、メソッドを呼び出すときにarg_two:を省略し、メソッド本体では変数arg_twoとしてアクセスできます。また、変数arg_threeは実際に関数呼び出しによって変更されることに注意してください。

9
Hless

Rubyでは、引数リストの最後にname => valueペアの束があるメソッドを呼び出すと、これらは自動的にHashにラップされ、最後の引数としてメソッドに渡されます。

def foo(kwargs)
  p kwargs
end

>> foo(:abc=>"def", 123=>456)
{:abc=>"def", 123=>456}

>> foo("cabbage")
"cabbage"

>> foo(:fluff)
:fluff

メソッドの記述方法について「特別な」ものは何もありません。それは、メソッドの呼び出し方法です。通常のハッシュオブジェクトをkwargsパラメータとして渡すことは完全に合法です。この構文ショートカットは、APIに名前付きパラメーターを実装するために使用されます。

Ruby記号は他の記号と同じように単なる値であるため、この例では、:first_nameは単なる通常の位置引数です。:presenceはハッシュキーとして使用される記号です。 –任意のタイプをハッシュキーとして使用できますが、記号は不変の値であるため、一般的な選択肢です。

5
millimoose

私はすべての回答が質問のポイントを逃したと思います。そして、それがシンボルが何であるかについてはっきりしていない-私は推測する-誰かによって尋ねられているという事実?

Rubyの初心者として、私は同様の混乱を抱えていました。私にとって、次のような答えの方が理にかなっているでしょう

メソッド引数は、渡された値によって入力されるローカル変数です。

シンボルの値を変更できないため、シンボルを引数自体として使用することはできません。

2
sevgun

シンボルはハッシュに限定されません。これらは識別子であり、文字列の余分なストレージスペースはありません。 「これは……」という言い方です。

検証呼び出しの可能な関数定義は次のようになります(簡単にするために、頭のてっぺんからそれが実際に何であるかわかりません):

def validates(column, options)
   puts column.to_s
   if options[:presence]
     puts "Found a presence option"
   end
 end

最初のシンボルがすべて独自のパラメーターであり、残りがハッシュであることに注意してください。

2
DGM