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)发出 AJAX GET 请求。当然,您需要为此设置路由和控制器。填充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" 选项简化以下代码,这样您既不需要追加新的数组项,也不需要手动选择名为“Select a State”的项。

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

最后,您可能希望将复杂的助手封装在对象中,以便更容易使用 Test::Unit 套件进行测试。看看这个截屏视频

谈到Controller,改变

# 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])) || []

当您只能调用一种方法时,请确保不要调用两种方法。改变

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

进入

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

我已经使用 Carmen 和 jQuery 写了一篇关于此的博客文章。该代码是可重用的,因为它存在于我的地址视图的一部分中。我通过表单中的fields_for“地址”标签使用它。您可以在此处阅读整个条目:http: //eric.lubow.org/2009/ruby/rails/country-state-select-using-carmen-and-jquery/

于 2010-03-10T19:57:21.920 回答