【问题标题】:refactoring common pattern in shared concerns重构共同关注点中的共同模式
【发布时间】:2021-12-28 17:58:57
【问题描述】:

应用程序具有具有重复模式的控制器操作方法。
本质上,在切换项目上添加或删除,计数器修改和切换状态改变。这些方法属于一个共同的关注点。 请注意,这些可能不一定是指同一类的对象
这是一种这样的方法:

def toggle_territory_criteria
  if params[:criteria] == "none" 
    if params[:toggle].to_i == 0
      @region_none_active = 0
      @regional_total = params[:regional_total].to_i - params[:value].to_i
    else
      @region_none_active = 1
      @regional_total = params[:regional_total].to_i + params[:value].to_i
    end
  else
    if params[:toggle].to_i == 0
      @active_regionminor_ids.delete(params[:criteria].to_i)
      @regional_total = params[:regional_total].to_i - params[:value].to_i
    else
      @active_regionminor_ids = params[:regionminors] << params[:criteria].to_i
      @regional_total = params[:regional_total].to_i + params[:value].to_i
    end
  end
end

这可以通过以下三种方法进行重构和完全抽象:

def toggle_state(attribute)
  attribute = false
  if params[:toggle].to_i == 0
    attribute = true
  end
end

def toggle_collection(id_collection, criteria_attribute)
  id_collection << criteria_attribute
  if params[:toggle].to_i == 0
    id_collection.delete(criteria_attribute)
  end
end

def toggle_sums(sum_value, original_sum, new_value)
  sum_value = original_sum + new_value
  if params[:toggle].to_i == 0
    sum_value = original_sum - new_value
  end
end

导致一个简洁的关注方法

def toggle_territory_criteria_too
  if params[:criteria] == "none"
    toggle_state(@region_none_active)
    toggle_sums(@regional_total, params[:regional_total].to_i, params[:value].to_i)
  else
    toggle_collection(@active_regionminor_ids, params[:criteria].to_i)
    toggle_sums(@regional_total, params[:regional_total].to_i, params[:value].to_i)
  end
end 

但是,在原始方法和视图中都无法访问结果变量(关注方法为此目的使用实例变量)。

执行此重构以服务于控制器操作的正确方法是什么?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    在 Ruby(当然也包括 Rails)中,方法永远不会更改它作为参数接收的对象的值,除非使用 破坏性 方法。

    在您的情况下,例如,当您运行 toggle_state(@region_none_active) 时,方法 toggle_state 永远不会更改 @region_none_activetoggle_state所做的只是返回最后执行的行的值,即if params[:toggle].to_i == 0的值如果为false,或者attribute = true的行的返回值,即true。方法toggle_state中的attribute是一个局部变量,改变它与@region_none_active无关。

    同样,方法toggle_sums 永远不会改变任何东西,它只是返回 Numeric 或 false(!),这取决于一组给定值作为属性。我敢肯定,您不会想要该方法中的值 false

    相反,以下将在您的关注方法中设置实例变量(在调用方),例如 @region_none_active

      @region_none_active = toggle_state(@region_none_active)
    

    您需要对代码中的其他方法进行类似的修改。该规范是 Ruby 的基本原则,因此请参阅 Ruby 参考资料或教科书了解详细信息(但我相信您知道吗?)。

    最后,如果你想从你的视图中访问实例变量@region_none_active,你可能需要为它编写自己的getter方法,比如

      # Your model
      attr_reader :region_none_active
      # And access it from your model "mdl" like
      #   mdl.region_none_active
    

    其中attr_reader
    def region_none_active; @region_none_active; end 的Ruby 内置别名


    注意,为了清楚起见,我建议您重写您的 toggle_state,如下所示,尽管它的作用与您的代码相同(此外,根据Ruby 的方法名称约定):

    def toggle_state(attribute)
      params[:toggle].to_i == 0
    end
    

    另一个注意事项是,您的代码中的两个方法id_collection &lt;&lt;id_collection.delete 具有破坏性,因此会修改调用者的对象。所以你需要小心处理它们。老实说,我不建议在方法中使用这种破坏性的方法,因为直接在用户方法中更改调用者的对象通常会使您的代码缺乏组织且难以阅读。总的来说,我会坚持使用非破坏性方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 2013-12-29
      • 1970-01-01
      相关资源
      最近更新 更多