Ruby の Mechanize の wiki のよてい

Mechanize::Form::SelectList


1項目しか選択できない選択メニュー、またはドロップダウンリスト全体を表現するクラスです。
<form name="selectform">
  <select name="memu2">
    <option value="1" selected>選択1</option>
    <option value="2">選択2</option>
    <option value="3">選択3</option>
  </select>
</form>

ラジオボタンやチェックボックスとは違い、選択リストは Mechanize においては若干複雑です(構造的には一番妥当なのですが)。この SelectList クラスは「選択メニュー全体」を表し、個々の項目を Mechanize::Form::Option クラスのオブジェクトとして保持しています。
メニューにあるひとつの項目を選択状態にするには、Mechanize::Form#field_with で SelectList オブジェクトを選んだ後に、#option_with で Option オブジェクトを選び、Mechanize::Form::Option#select で項目を確定します。

上記の HTML の例で言うと、選択2を選択状態にするには
form.field_with(:name => 'menu2'){|list|
  list.option_with(:text => '選択2').select
}
となります。#value= を利用すると、「表示」しているものを無視して直接
form.field_with(:name => 'menu2'){|list|
  list.value = "2"
}
と指定することもできます。なお、Mechanize::Form#[]= は vakue= メソッドを利用するので、
form['memu2'] = "2"
と短く書くことも可能です。通常の入力欄での書き方と変わらなくなります。
ユーザーが選択を行わなかった場合、HTML 上で selected 要素が書かれていればその項目の value が送信されます。ユーザーが選択を行わず、selected 要素も無かった場合、メニューの一番最初の項目の value が送信されます。これは一応 RFC に沿った動作ですが、あまり意識されていない(あまり実装されていない?)ので注意してください。

#options に含まれる項目はひとつしか選択状態にできません。Mechanize::Form::Option#select#value= で選択状態にするたびに、他の項目の選択状態が自動で解除されています。
select 要素に multiple が指定してあって(通常のWebブラウザではCtrlキー併用などで)複数選択できるような場合は Mechanize::Form::MultiSelectList が担当します。
Mechanize::Form::MultiSelectList を継承しています(結果的に Mechanize::Form::Field のメソッドも利用できます)。継承されたメソッドの中には項目を全選択するものなどもありますが、この SelectList クラスではうまく動作しないことがあります。よくない継承なので、MultiSelectList を継承していることは忘れてください。解説も有効なものに限定します。



Mechanize::Form::SelectList オブジェクトを生成します。ユーザーが使用することはありません。

この選択メニューの名前を文字列で指定します。
Mechanize::Form::Field#name= を参照してください。
<select name="list1" size="4">
という HTML の場合、name メソッドは文字列 "list1" を返します。

この選択メニューを作成したときに使用した HTML ノードを Nokogiri::HTML::Element? 等で返します。
Mechanize::Form::Field#node を参照してください。
<select> から </select> までパースされたものが返ります。
option_with(pattern){|option| optional_non_ensure_block}

{メソッド名 => 返り値} という引数 pattern を満たす Mechanize::Form::Option オブジェクトを #options から探し、最初のものを返します。
# 「北海道」と書かれている項目を正規表現で適当に選択
agent.page.forms[0].field_with(:name => 'area').option_with(:text => /北海道/).select #utf-8
# value が 3 である項目を選択
agent.page.forms[0].field_with(:name => 'area').option_with(:value => '3').select
動作は Mechanize::Form#xxxx_with を参照してください。
有効なメソッドと値のペアは Mechanize::Form::Option のメソッドと返り値になります。
Mechanize::Form::Option には name メソッドがないので、他の _with 系メソッドのように引数に文字列を指定すると NoMethodError が出て落ちます。使用しないでください。

このメニューに含まれる個々の項目を Mechanize::Form::Option オブジェクトにして配列で返します。
Mechanize::Form::MultiSelectList#options を参照してください。
条件による抽出は #option_with で行うことができます。
options_with(pattern){|option| optional_non_ensure_block}

{メソッド名 => 返り値} という引数 pattern を満たす Mechanize::Form::Option オブジェクトを #options から探し、全てを配列で返します。
該当がない場合は空の配列 [] を返します。
…これは Mechanize::Form::MultiSelectList にあるべきメソッドです。Mechanize 1.0.0 時点ではまだ移動されていません。

#options 内で Mechanize::Form::Option#selected が true を返す項目オブジェクトの Mechanize::Form::Option#value を文字列で返します。
つまり、選択状態にある項目の値を返します。擬似的には selectlists[0].option_with(:selected => true).value で、細かくは
  • 普通にユーザーが #value=Mechanize::Form::Option#select 等で選択を行っていた場合は、その最新の value
  • まだユーザーが選択を行っていなくて、HTML で selected の指定がされた項目があれば、その value
  • ユーザーが選択を行っておらず、HTML で selected の指定もされていなければ、#options の先頭の value
…を、返します。
項目自体がない、#options が空の配列を返す状態だった場合にのみ、nil を返します。


指定した文字列を value にもつ項目オブジェクトを #options から探し、選択状態にします。
agent.page.form_with(:name => 'selectform'){|form|
  form.field_with(:name => 'menu2'){|list|
    # <option value="2">選択2</option> を選択する
    list.value = '2'
  }
}
#options に含まれる Mechanize::Form::Option オブジェクトと連動しており、引数に等しい value を持つ項目の Mechanize::Form::Option#selected は true を、該当しない他の全項目は false を返すようになります。つまり、次のHTML
<form name="selectform">
  <select name="memu2">
    <option value="1" selected>選択1</option>
    <option value="2">選択2</option>
    <option value="3">選択3</option>
  </select>
</form>
で表される選択リストで、2番目の選択肢(選択2)を選ぶ場合、
form.field_with(:name => 'menu2').value = '2'

form.field_with(:name => 'menu2').option_with(:value => '2').select
は内部動作的には同一になります。
等しい value を持つ項目が無い場合でも、指定した value 自体は保持され送信されます。エラー等は出ないので注意してください。
全ての選択を何らかの理由で一旦解除したいという場合は、引数に nil を指定するようなことはせずに Mechanize::Form::MultiSelectList#select_none を行ってください。
内部的にはわりと面妖な動作をしているので、あまり深入りせずに普通に使うのがいいと思われます。該当無し時の一時値は select_none か再度の value= で削除されます。



HTML 上での出現位置を引数のオブジェクトと比較し、自分が前なら -1 を、自分が後ろなら 1 を、同一ノード由来なら 0 を返します。
Mechanize::Form::Field#<=> を参照してください。

この選択メニューの名前を返す #name メソッドの返り値を文字列 str に変更します。
Mechanize::Form::Field#name を参照してください。

この選択メニューの HTML ノードを返す #node メソッドの返り値を node_obj に変更します。
Mechanize::Form::Field#node= を参照してください。

送信用データの配列を作成して返します。
#name#value が組になったネストした配列が返ります。HTML 上でのデフォルトがなく、ユーザーが選択行為を行っていない場合でも、メニューの1番目の値が送信されるので注意してください(#value 参照)。
空のメニューだった場合には nil が返ります。

管理人/副管理人のみ編集できます