2

条件付きの国別選択ドロップダウンを開発しました。この動作をアドレスモデルに除外して、動的な動作(ビューとコントローラーの間で多かれ少なかれ分割)を毎回コピーする必要がないようにします。ユーザーが完全なアドレスを入力できるようにしたい。

基本的に、私はつま先をDRYに少し深く浸そうとしています。しかし、ビヘイビアーをどこに埋め込むかは正確にはわかりません。モデルまたはヘルパーを使用して必要なフォームを作成しますか?最も重要なこと:状態のリストを更新するための動的な動作をどこでどのように呼び出すことができますか?アドレスコントローラーが必要ですか、それともモデル内からすべて実行できますか?

言い換えれば、私が今ビューに持っているものは次のようなものです:

  # _refine.html.erb
      <tr>
        <td>
        <%= label_tag :dest_country, 'Country: ' %></td><td>
          <%= select_tag :dest_country, 
            options_for_select(Carmen::country_names 
                      << 'Select a country', 
                :selected => 'Select a country'), 
            {:include_blank => true,
            :id => 'country_select',                              
            :style => 'width: 180px',
            :onchange => remote_function(
              :url => {:action => 'update_state_select'},
              :with => "'country='+value")} %>
        </td>      
      </tr>
      <tr>
          <div id="state_select_div">
            <td><%= label_tag :dest_state, 'State: &nbsp&nbsp' %></td>
            <td><%= select_tag :dest_state, 
                        options_for_select(Carmen::states('US').collect{
                                |s| [s[0],s[0]]} << ['Select a state'], 
                                :selected => 'Select a state'), 
                                {:style => 'width: 180px'} %></td>
          </div>      
      </tr>

更新メソッドはコントローラーにあります。

# search_controller.rb

def update_state_select
  # puts "Attempting to update states"
  states = []
  q = Carmen::states(Carmen::country_code(params[:country]))
  states = q unless q.nil? 
  render :update do |page|
    page.replace_html("state_select_div",
    :partial => "state_select",
    :locals => {:states => states }
  )
 end
end

最後に、固有名または空白のテキストフィールドでドロップインされるパーシャルがあります。

# _state_select.html.erb
<% unless states.empty? or states.nil? %>
      <%= label_tag :dest_state, 'Select a state'  %>
 <br/> <%= select_tag :dest_state, 
                     options_for_select(states.collect{|s| [s[0],s[0]]}  
                         << ['Select a state'], 
                       :selected => 'Select a state'), 
                       {:style => 'width: 180px'} %>
 <% else %>
   <%= label_tag :dest_state, 'Please enter state/province' %><br />
   <%= text_field_tag :dest_state %>
<% end %>

さて、私がやりたいのは、モデルを介して住所を関連付け(たとえば、Person has_one:address)、新しい人物を作成するためのフォーム内で、次のようなものを使用できるようにすることです。

 <%= label_tag :name, 'What's your name?' %>
 <%= text_field_tag :name %>
 <%= label_tag :address, 'Where do you live?' %>
 <%= address_fields_tag :address %>

これにより、適切なドロップダウンが生成され、動的に結合され、その結果にPerson.address.countryおよびPerson.address.stateからアクセスできます。

前もって感謝します!

4

3 に答える 3

2

まず、コードを正しく理解していることを確認しましょう。ユーザーが[国]選択ボックスを変更し、サーバーに対してAJAX要求が行われると、サーバーは[状態]ボックスを正しいエントリで更新するスクリプトを送り返しますか?

もしそうなら、私は完全に異なる戦略を使用します。dest_countryが変更されたときにトリガーされるコールバックを使用します。このコールバックに、たとえば/countries/{COUNTRY}/states.json(または.xml)へのAJAXGETリクエストを実行させます。もちろん、このためにルートとコントローラーを設定する必要があります。戻りdest_state値を入力します。

更新:ユーザーインターフェイスコードの除外については、パーシャルとヘルパーを使用してみてください。http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

于 2009-06-24T17:02:08.303 に答える
1

データはモデルに属し、プレゼンテーションはテンプレート(およびヘルパー)に属します。そうは言っても、私はデータをプレゼンテーションから分離し、役に立たないコードを削除し始めるでしょう。

states.collect{|s| [s[0],s[0]]}

AFAIK、この実行は必要ありません。あなたはそれを単純化することができます

states.collect{|s| s[0]}

また

states.collect(&:first)

ただし、最も重要なのは、Carmenクラスにカスタムメソッドを提供して、正しい形式でデータを取得できることです。

また、:prompt => "Select a State"オプションを使用して次のコードを簡略化すると、新しい配列アイテムを追加したり、 "SelectaState"というアイテムを手動で選択したりする必要がなくなります。

options_for_select(Carmen::states('US').collect{
                                |s| [s[0],s[0]]} << ['Select a state'], 
                                :selected => 'Select a state'),

最後に、複雑なヘルパーをオブジェクトにカプセル化して、Test::Unitスイートでのテストを容易にすることができます。このスクリーンキャストをチェックしてください。

コントローラーについて話して、変更します

# puts "Attempting to update states"
states = []
q = Carmen::states(Carmen::country_code(params[:country]))
states = q unless q.nil? 

の中へ

# puts "Attempting to update states"
states = Carmen::states(Carmen::country_code(params[:country])) || []

1つだけを呼び出すことができる場合は、2つのメソッドを呼び出さないようにしてください。変化する

<% unless states.empty? or states.nil? %>

の中へ

<% unless states.blank? %>
于 2009-06-22T17:50:21.340 に答える
0

CarmenとjQueryを使用してこれに関するブログ投稿を書きました。コードは私のアドレスビューの一部に存在するため、再利用できます。フォームのfields_for「address」タグで使用します。ここでエントリ全体を読むことができます:http://eric.lubow.org/2009/ruby/rails/country-state-select-using-carmen-and-jquery/

于 2010-03-10T19:57:21.920 に答える