我有这样的代码,用于在我的表单中进行链选择 查看索引操作:
<%= form_tag do %>
<%= collection_select(*@brands_select_params) %>
<%= collection_select(*@car_models_select_params) %>
<%= collection_select(*@production_years_select_params) %>
<% # Пока еще никто ничего не выбрал %>
<%= submit_tag "Send", :id => "submit", :name => "submit" %>
我的控制员:
class SearchController < ApplicationController
def index
@brands = Brand.all
@car_models = CarModel.all
if (params[:brand].blank?)
@brands_select_params = [:brand, :id, @brands, :id, :name, :prompt => "Выбирай брэнд"]
if params[:car_model].blank?
@car_models_select_params = [:car_model, :id, @car_models, :id, :name, { :prompt => "Model" }, \
{ :disabled => "disabled" }]
@production_years_select_params = [:production_year, :id, @car_models, :id, :name, { :prompt => "Year" }, \
{ :disabled => "disabled" }]
end
else
@brands_select_params = [:brand, :id, @brands, :id, :name, { :selected => params[:brand][:id] } ]
if params[:car_model].blank?
@car_models_select_params = [:car_model, :id, Brand.find(params[:brand][:id]).car_models, :id, :name, \
{ :prompt => "And model now" } ]
@production_years_select_params = [:production_year, :id, @car_models, :id, :name, { :prompt => "Year" }, \
{ :disabled => "disabled" } ]
else
@car_models_select_params = [:car_model, :id, Brand.find(params[:brand][:id]).car_models, :id, :name, \
{ :selected => params[:car_model][:id] } ] unless params[:car_model][:id].empty?
@production_years_select_params = [:production_year, :id, CarModel.find(params[:car_model][:id]).production_years, :id, :year, \
{ :prompt => "And year now" } ] unless params[:car_model][:id].empty?
end
end
end
end
如您所见,我的控制器代码中有太多ifs。我会在那里添加更多条件。之后,任何阅读该代码的人都会受到脑损伤。所以我只想以真正的Ruby方式制作它,但不知道如何。伙计们,请帮忙。我应该如何重构这一堆废话?
答案 0 :(得分:5)
我认为问题的一大部分是你在控制器中做得太多了。应该在视图和视图助手中完成生成标记(以及包括为表单助手构建参数列表的IMO)。所以:
module SearchHelper
def brand_select brands, options={}
collection_select :brand, :id, brands, :id, :name, :options
end
def car_model_select car_models, options={}
collection_select :car_model, :id, car_models, :id, :name, options
end
def production_year_select years, options={}
collection_select :production_year, :id, years, :id, :year, options
end
end
然后你可以将你的控制器切到这个:
def index
@brands = Brand.all
@car_models = CarModel.all
@selected_brand_id = params[:brand] && params[:brand][:id]
@selected_car_model_id = params[:car_model] && params[:car_model][:id]
@production_years = @selected_car_model_id ?
[] : CarModel.find(@selected_car_model_id).production_years
end
在你看来:
<%= brand_select @brands, :prompt => "Выбирай брэнд",
:selected => @selected_brand_id
%>
<%= car_model_select @car_models, :prompt => "Model",
:selected => @selected_car_model_id
%>
<%= production_year_select @production_years, :prompt => "Year",
:selected => @selected_car_id
%>
我怀疑你可以使用form_for
and fields_for
进一步简化这一点,并完全摆脱帮助者,但这取决于你的模型关联的设置方式。
答案 1 :(得分:2)
这种问题没有明显的解决方案。
通常,我会尽量保持if
/ else
架构,并将所有代码导出到不同的方法中。这里有两个优点:
可读性
更容易进行单元测试
对于您的情况,它将是:
class SearchController < ApplicationController
def index
@brands = Brand.all
@car_models = CarModel.all
if (params[:brand].blank?)
@brands_select_params = [:brand, :id, @brands, :id, :name, :prompt => "Выбирай брэнд"]
if params[:car_model].blank?
@car_models_select_params, @production_years_select_params = get_card_model(@car_models)
end
else
@brands_select_params = [:brand, :id, @brands, :id, :name, { :selected => params[:brand][:id] } ]
if params[:car_model].blank?
@car_models_select_params, @production_years_select_params = foo_method(@car_models)
else
@car_models_select_params, @production_years_select_params = bar_method
end
end
end
def get_card_model car_models
[
[:car_model, :id, car_models, :id, :name, { :prompt => "Model" }, { :disabled => "disabled" }],
[:production_year, :id, car_models, :id, :name, { :prompt => "Year" }, { :disabled => "disabled" }]
]
end
end