Ruby Mechanize wiki (ja) - Mechanize::Form::MultiSelectList

Mechanize::Form::MultiSelectList


複数選択可能な選択メニュー全体を表すクラスです。

<form name="mselect_test">
  <select name="select3" size="3" multiple>
    <option value="one" selected>選択1</option>
    <option value="two">選択2</option>
    <option value="three">選択3</option>
  </select>
</form>
#options に選択項目の Mechanize::Form::Option オブジェクトをまとめた配列を保持しています。
Ctrl キーなどを併用してクリックしなければならず利用方法が意外とめんどくさい(というかそもそも複数選択であることに気づいてもらえない)上に内容的にはチェックボックスなどでも代用可能であるため、最近はあまり見ないタイプのメニューです。
Mechanize 1.0.0 現在、option_with も options_with も実装されていないので、含まれる Mechanize::Form::Option オブジェクトの選択は Mechanize::Form::SelectList に比べて大変面倒になっています。#options を配列としてアクセスしてください。
agent.page.form_with(:name => 'mselect_test'){|form|
  form.field_with(:name => 'select3'){|menu|
    # HTML上のselectedをクリアして項目を全て無選択にする
    menu.select_none
    # value が one であるメニューをfindで探し、選択
    menu.options.find{|o| o.value == 'one'}.select
    # value が one であるメニューをfindで探し、選択択
    menu.options.find{|o| o.value == 'three'}.select
  }
}
#value= を利用すると、「表示」しているものを無視して直接
agent.page.form_with(:name => 'mselect_test'){|form|
  form.field_with(:name => 'select3'){|menu|
    menu.value = ['one', 'three']
  }
}
と書くことができます。最終的に選択状態にしたい項目の value だけを配列で指定します(select_noneは不要)。なお、Mechanize::Form#[]= は value= メソッドを利用するので、
agent.page.form_with(:name => 'mselect_test'){|form|
  form['select3'] = ['one', 'three']
}
と短く書くことも可能です。

「チェックされている項目はいじらずに1項目だけ追加クリック」したい場合は、value= メソッドは使わずに
agent.page.form_with(:name => 'select_test1'){|form|
  form.field_with(:name => 'select3'){|menu|
    menu.options.find{|o| o.value == 'two'}.select 
  }
}
のように、個々の Option オブジェクトの Mechanize::Form::Option#select メソッドを使わなければなりません。



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

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

この入力欄オブジェクトを作成したときに使用した HTML ノードを Nokogiri::HTML::Element? 等で返します。
Mechanize::Form::Field#node を参照してください。
<select> から </select> までパースされたものが返ります。

このメニューに含まれる個々の項目を Mechanize::Form::Option オブジェクトにして配列で返します。
項目が含まれていない場合は空の配列 [] を返します。
該当する HTML は以下の通り。
  • <option>...</option>
配列要素は HTML 上での単純な出現順になります。
<form name="mselect_test">
  <select name="select3" size="3" multiple>
    <option value="one" selected>選択1</option>
    <option value="two">選択2</option>
    <option value="three" selected>選択3</option>
  </select>
</form>
に対して
irb> p agent.page.form('mselect_test').options.map{|o| o.text}
["選択1", "選択2", "選択3"]

条件による抽出を行う options_with のようなメソッドは Mechanize 1.0.0 では存在しません。配列とみなして Array#find などで探してください。
# value が "one" な項目だけを選択する
form.field_with(:name => 'select3'){|menu|
  menu.select_none
  menu.options.find{|o| o.value == 'one'}.select
# value が "one" な項目を追加選択する
form.field_with(:name => 'select3'){|menu|
  menu.options.find{|o| o.value == 'one'}.select

#options に含まれている全ての Mechanize::Form::Option オブジェクトに対して Mechanize::Form::Option#tick を実行します。
項目を全て選択された状態にします。#value= において #options に存在しない value の値を指定していた場合、それは削除されます。

#options に含まれている全ての Mechanize::Form::Option オブジェクトに対して Mechanize::Form::Option#untick を実行します。
項目を全て非選択の状態にします。#value= において #options に存在しない value の値を指定していた場合も削除されます。

#options 内で Mechanize::Form::Option#selected? が true を返す項目オブジェクトを全て配列で返します。
つまり、選択状態にある項目オブジェクトを全て返します。

選択状態にしたい複数項目の value 要素を配列で直接指定します。
form.field_with(:name => 'select3'){|menu|
  menu.value = ['one', 'three']
}
これは #options と連動しており、
  • 引数に等しい value を持つ項目は選択状態に
  • 該当しない他の全項目は非選択状態に
なります(つまり #select_none してから該当だけ Mechanize::Form::Option#select)。
form.field_with(:name => 'select3'){|menu|
  p menu.option_with(:value => 'one').selected? #=> false
  menu.value = ['one', 'three']
  p menu.option_with(:value => 'one').selected? #=> true
}
引数 values は文字列を要素とした配列です。1項目だけを選択したいという場合は文字列でも構いません。
既存の選択は全て解除された上で再選択されます。既存の選択を保持したまま「追加」で選択を行いたいという場合は、追加したい項目の Mechanize::Form::Option オブジェクトを #options から Array#find などで探して Mechanize::Form::Option#select を行ってください。
全項目を一旦非選択にしたい場合は #select_none が、全項目を選択したい場合は #select_all が簡単です。
等しい value を持つ項目が無かったような場合も、指定した value 自体は保持され送信されます(エラーなどは出ません)。この一時値は、select_none か select_all か再度の value= で削除されます。

現在選択状態にある項目の value 属性値を配列で返します。
つまり、おおむね #selected_options.map{|o| o.value} です。
なお、Mechanize::Form::Option#selectMechanize::Form::Option#unselect は既存の選択をリセットしないので、HTML 属性の selected でデフォルト選択になっていた「ユーザーが触ってない項目」が返ってくることがあります(#value= は既存選択リセットの上選択)。
選択された状態のものがなかった場合は空の行列 [] を返します。
#value= において選択肢に無い value の値を指定していた場合は、返り値の先頭のほうに挿入されて返ってきます。
好きな果物:
<form name="f1">
  <select name="fav_fruits" size="2" multiple>
    <option value="one" selected>りんご</option>
    <option value="two">みかん</option>
  </select>
</form>
form.field_with(:name=>'fav_fruits'){|menu|
  menu.value=['みかん', 'メロン']
  p menu.value #=> ["メロン", "みかん"]
}



HTML 上での出現位置を引数のオブジェクトと比較し、sort 可能な答を返します。
Mechanize::Form::Field#<=> を参照してください。

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

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

送信用データの配列を作成して返します。
#value の各々の要素と #name を組にしたネストした配列が返ります。Mechanize::Form#build_query 内で呼ばれます。
  form.field_with(:name => 'select3'){|menu|
    menu.select_none
    menu.options.find{|o| o.value == 'one'}.select
    menu.options.find{|o| o.value == 'three'}.select
    p menu.query_value #=> [['select3', 'one'], ['select3', 'three']]
#value が空、つまり選択状態の項目が無かった場合は空の配列 [] を返します。