在控制器操作内部重构 params[...] 的许多 if 语句

发布于 2024-12-06 13:28:02 字数 2262 浏览 2 评论 0 原文

我有这样的代码,用于在我的表单中进行链选择 查看索引操作:

<%= 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

如您所见,我的控制器代码中有太多 if 语句。我会在那里添加更多条件。此后,任何读过该代码的人都会受到大脑损坏。所以我只想以真正的 Ruby 方式实现它,但不知道如何。请帮忙,伙计们。我应该如何重构这堆废话?

I have such code, for making chain selects in my form
View for index action:

<%= 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" %>

And my controller:

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

As you can see, too many ifs in my controller code. And i gonna add more conditions there. After that anyone who read that code will get brain corruption. So i just wanna make it in real Ruby way, but don't know how. Please, help, guys. How should i refactor this bunch of crap?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

懷念過去 2024-12-13 13:28:02

我认为问题的很大一部分是你在控制器中做了太多的事情。生成标记(以及 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_forfields_for 并完全摆脱助手,但这在一定程度上取决于模型关联的设置方式。

I think a big part of the problem is you're doing too much in your controller. Generating markup (and IMO that includes building parameter lists for form helpers) should be done in views and view helpers. So:

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

Then you can cut your controller down to this:

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

And in your view:

<%= 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
%>

I suspect you could simplify this even more using form_for and fields_for and get rid of the helpers entirely, but it depends a bit on how your model associations are set up.

情定在深秋 2024-12-13 13:28:02

此类问题没有明显的解决方案。

一般来说,我尝试保持 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

There is no obvious solution to this kind of problem.

Generally, I try to keep the if / else architecture very clear and export all code into separate methods. 2 advantages here:

  • readability

  • easier unit testing

For your case, it would be:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文