我已经开发了偶然的国家/地区选择下拉列表,我想将此行为分解为地址模型,这样我就不必复制动态行为(在视图和控制器之间或多或少分开)每次我希望用户能够输入完整的地址。
基本上我正试图让我的脚趾更深入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:   ' %></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:地址)关联地址,并在表单中创建新人,能够使用像
<%= 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访问。
提前致谢!
答案 0 :(得分:2)
首先让我确保我正确理解代码;当用户更改国家/地区选择框时,向服务器发出AJAX请求,然后服务器发送回更新状态框的脚本以及正确的条目?
如果是这样,我会采用完全不同的策略。使用在dest_country
更改时触发的回调。让这个回调对例如AJAX GET请求做/countries/{COUNTRY}/states.json(或.xml)。当然,您需要为此设置路由和控制器。使用返回的值填充dest_state
。
更新: 至于分解用户界面代码,请尝试使用partials和helpers。 http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
答案 1 :(得分:1)
数据属于模型,演示文稿属于模板(和帮助程序)。 这就是说我会开始从演示文稿中分离数据并删除无用的代码。
states.collect{|s| [s[0],s[0]]}
AFAIK,不需要执行此操作。您可以将其简化为
states.collect{|s| s[0]}
或
states.collect(&:first)
但最重要的是,您可以在Carmen类中提供自定义方法,以便以正确的格式获取数据。
使用以下代码可以简化以下代码:prompt =&gt; “选择状态”选项,这样您既不需要附加新数组项,也不需要手动选择名为“选择状态”的项目。
options_for_select(Carmen::states('US').collect{
|s| [s[0],s[0]]} << ['Select a state'],
:selected => 'Select a state'),
最后,您可能希望将复杂的帮助器封装在对象中,以便更容易使用Test :: Unit套件进行测试。查看this screencast。
谈论控制器,改变
# 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? %>
答案 2 :(得分:0)
我使用Carmen和jQuery写了一篇关于此的博文。代码是可重用的,因为它在我的地址视图中处于部分状态。我在表单中使用 fields_for“address”标记。您可以在此处阅读完整条目:http://eric.lubow.org/2009/ruby/rails/country-state-select-using-carmen-and-jquery/。