执行此代码 kata,我必须从以下方法中删除尽可能多的 if 语句:
# returns permissions if user is set in security context
def get_user_permissions
user_permissions = Set.new
if (@user != nil)
user_permissions << :DEFAULT_PERMISSION
if (has_cm_team_role)
user_permissions << :CM_TEAM_ROLE_PERMISSION
end
if (has_cm_invoice_view_role || has_invoice_finance_role)
user_permissions << :CM_INVOICE_USER_PERMISSION
user_permissions << :INVOICE_VIEW_PERMISSION
user_permissions << :ACCESS_ALL_INVOICE_PERMISSION
end
if (has_invoice_finance_role)
user_permissions << :FINANCE_INVOICE_PERMISSION
end
if (has_application_access)
user_permissions << :CM_INVOICE_USER_PERMISSION
end
if (has_application_access(:CM_INVOICE_ROLE))
user_permissions << :CM_ANY_INVOICE_PERMISSION
end
if (has_application_access(:PA_INVOICE_ROLE))
user_permissions << :PA_ANY_INVOICE_PERMISSION
end
if (has_application_access(:SDT_INVOICE_ROLE))
user_permissions << :SDT_ANY_INVOICE_PERMISSION
end
end
user_permissions
end
我的第一次尝试几乎成功了,但有一些测试失败了:
def get_user_permissions
user_permissions = Set.new
if (@user != nil)
user_permissions << :DEFAULT_PERMISSION
# add the permissions in another method
add_permissions(user_permissions)
end
user_permissions
end
def add_permissions(user_permissions)
# a hash where each key is a condition, and each value is a permission
hash = {
has_cm_team_role => :CM_TEAM_ROLE_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :CM_INVOICE_USER_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :INVOICE_VIEW_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :ACCESS_ALL_INVOICE_PERMISSION,
has_invoice_finance_role => :FINANCE_INVOICE_PERMISSION,
has_application_access => :CM_INVOICE_USER_PERMISSION,
has_application_access(:CM_INVOICE_ROLE) => :CM_ANY_INVOICE_PERMISSION,
has_application_access(:PA_INVOICE_ROLE) => :PA_ANY_INVOICE_PERMISSION,
has_application_access(:SDT_INVOICE_ROLE) => :SDT_ANY_INVOICE_PERMISSION
}
# loop through the hash and add permissions if the key is true
hash.each do |condition, permission|
if (condition)
user_permissions << permission
end
end
这种方法的问题在于,每个. 所以我通过使用 Procs 来解决这个问题,如下所示:
def add_permissions(user_permissions)
hash = {
Proc.new{has_cm_team_role} => :CM_TEAM_ROLE_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :INVOICE_VIEW_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :ACCESS_ALL_INVOICE_PERMISSION,
Proc.new{has_invoice_finance_role} => :FINANCE_INVOICE_PERMISSION,
Proc.new{has_application_access} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_application_access(:CM_INVOICE_ROLE)} => :CM_ANY_INVOICE_PERMISSION,
Proc.new{has_application_access(:PA_INVOICE_ROLE)} => :PA_ANY_INVOICE_PERMISSION,
Proc.new{has_application_access(:SDT_INVOICE_ROLE)} => :SDT_ANY_INVOICE_PERMISSION
}
hash.each do |condition, permission|
if (condition.call)
user_permissions << permission
end
end
end
好的,这可行,并且测试都通过了,但是我将所有键转换为 Procs,以便其中 3 个正确评估。我宁愿只在需要时使用 Procs,即第二个、第三个和第四个键,如下所示:
def add_permissions(user_permissions)
hash = {
# just use the method name unless a Proc is required
has_cm_team_role => :CM_TEAM_ROLE_PERMISSION,
# use a Proc here, so that the OR is evaluated later
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :INVOICE_VIEW_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :ACCESS_ALL_INVOICE_PERMISSION,
has_invoice_finance_role => :FINANCE_INVOICE_PERMISSION,
has_application_access => :CM_INVOICE_USER_PERMISSION,
has_application_access(:CM_INVOICE_ROLE) => :CM_ANY_INVOICE_PERMISSION,
has_application_access(:PA_INVOICE_ROLE) => :PA_ANY_INVOICE_PERMISSION,
has_application_access(:SDT_INVOICE_ROLE) => :SDT_ANY_INVOICE_PERMISSION
}
然后某种方法来确定键是否是 Proc,如果是,则调用它,但如果不是,则将条件视为任何其他键:
hash.each do |condition, permission|
if condition.is_proc?
if (condition.call)
user_permissions << permission
end
elsif condition
user_permissions << permission
end
end
end
有小费吗?有什么比我尝试这样做更好的想法吗?通过这样做,我是否让它变得更加循环复杂?我应该坚持使用我所有的键都是 Procs 的工作解决方案吗?