你会如何整理这个控制器逻辑?
我在控制器中有一些逻辑,如果满足某些条件,则设置对象的状态:
if params[:concept][:consulted_legal] == 0 && params[:concept][:consulted_marketing] == 1 @concept.attributes = {:status => 'Awaiting Compliance Approval'} elsif params[:concept][:consulted_marketing] == 0 && params[:concept][:consulted_legal] == 1 @concept.attributes = {:status => 'Awaiting Marketing Approval'} elsif params[:concept][:consulted_marketing] == 0 && params[:concept][:consulted_legal] == 0 @concept.attributes = {:status => 'Awaiting Marketing & Legal Approval'} else @concept.attributes = {:status => 'Pending Approval'} end
我在创建和更新操作之间共享。 你会如何重构这种肮脏的东西? 寻找最佳实践。
编程新手并热衷于清理我的代码。
TIA。
这是我的看法。 我称之为Super DRY。
statuses = [ ['Awaiting Marketing & Legal Approval','Awaiting Compliance Approval'], ['Awaiting Marketing Approval','Pending Approval'] ] {:status => statuses[params[:concept][:consulted_legal].to_i][params[:concept][:consulted_marketing].to_i]}
或者,更传统的方法 – 冗长但可读:
status = if params[:concept][:consulted_legal] == "0" if params[:concept][:consulted_marketing] == "1" 'Awaiting Compliance Approval' else 'Awaiting Marketing & Legal Approval' end else if params[:concept][:consulted_marketing] == "0" 'Awaiting Marketing Approval' else 'Pending Approval' end end @concept.attributes = {:status => status}
注意 :看起来您的原始代码正在检查复选框的值。 params
散列中的值总是 Strings
,而不是Fixnum
所以我的代码比较字符串。 如果由于某种原因比较Fixnum
s是您的情况所需要的,只需取出数字周围的引号。
您可以使您的代码更少地依赖于这两个条件,并使其更加灵活。
waiting_on = [] waiting_on << 'Compliance' unless params[:concept][:consulted_marketing] waiting_on << 'Legal' unless params[:concept][:consulted_legal] status = waiting_on.empty? ? "Awaiting #{waiting_on.join(' & ')} Approval" : 'Pending Approval' @concept.attributes = {:status => status}
无filter的创建和更新版本:
def create set_concept_status_attribute ... end def update set_concept_status_attribute ... end private def set_concept_status_attribute waiting_on = [] waiting_on << 'Compliance' unless params[:concept][:consulted_marketing] waiting_on << 'Legal' unless params[:concept][:consulted_legal] status = waiting_on.empty? ? "Awaiting #{waiting_on.join(' & ')} Approval" : 'Pending Approval' @concept.attributes = {:status => status} end
或者使用before_filter:
before_filter :set_concept_status_attribute, :only => [:create, :update] def create ... end def update ... end
如果你可以将它移动到你的视图,它看起来更好:
module ConceptHelper def get_concept_status ... end end <%= get_concept_status %>
这看起来像是业务逻辑,所以它应该在模型中。
您的模型可能需要几个属性:consulted_legal和consulted_marketing,以及在其中任何一个更改时设置状态的方法:
before_update :set_status def set_status if consulted_legal && consulted_marketing status = "Pending Approval" elif consulted_legal && !consulted_marketing status = "Awaiting Marketing Approval" elif !consulted_legal && consulted_marketing status = "Awaiting Legal Approval" elif !consulted_legal && !consulted_marketing status "Awaiting Marketing & Legal Approval" end true # Needs to return true for the update to go through end
将其分解为嵌套的if语句。
if params[:concept][:consulted_legal] == '0' if params[:concept][:consulted_marketing] == '1' @concept.attributes = { :status => 'Awaiting Compliance Approval' } else @concept.attributes = { :status => 'Awaiting Marketing & Legal Approval' } end else if params[:consulted_marketing] == '1' @concept.attributes = { :status => 'Awaiting Marketing Approval' } else @concept.attributes = { :status => "Pending Approval" } end end
您可能认为所咨询的部门列表是一个足够固定的概念来certificate名为consulted_marketing等的变量。但对于增长和干燥(在某种程度上),我更喜欢一个部门列表。
你真正拥有的是工作流程或状态机,我认为带有转换的deparments列表会产生最干净,最易增长的代码。
代码就是数据! 为您的数据建模,代码将是微不足道的。
这对我来说似乎是一个商业规则。 因此,您可能希望将其包装到函数中:
string GetConceptStatus(bool consulted_legal, bool consulted_marketing) { if (consulted_legal && consulted_marketing) { return "Pending Approval"; } if (consulted_legal && !consulted_marketing) { return "Awaiting Marketing Approval"; } if (!consulted_legal && consulted_marketing) { return "Awaiting Legal Approval"; } if (!consulted_legal && !consulted_marketing) { return "Awaiting Marketing & Legal Approval"; } }
这也将界面中bool
的编码细节与业务规则的实际实现分开。
但是代码的实际结构对我来说很好,因为它可能更好地模拟业务规则。