Ruby:将两个类似的方法合并为一个?

时间:2013-03-21 21:48:03

标签: ruby coding-style

我的Ruby对象中有两个类似的方法用于Rails应用程序。我知道他们可以合并,我只是不知道如何。 (如果你能找到一种更美妙的方法来处理除return unless以外的可能的nils,而不是使用#try,则可以获得额外的分数。)

 def is_portal_admin?(resource)
    return unless resource.user && resource.user.clinic_memberships.any?
    memberships = resource.user.clinic_memberships.collect { |membership| membership.portal_admin? }
    memberships.include?(true)
  end

  def is_staff_admin?(resource)
    return unless resource.user && resource.user.clinic_memberships.any?
    memberships = resource.user.clinic_memberships.collect { |membership| membership.staff_admin? }
    memberships.include?(true)
  end

4 个答案:

答案 0 :(得分:3)

怎么样:

def is_admin_of_type?(type, resource)
  return unless resource.user && resource.user.clinic_memberships.any? && type
  memberships = resource.user.clinic_memberships.collect { |membership| membership.send("#{type}_admin?") }
  memberships.include?(true)
end

如果有人提供不存在的类型,则会抛出NoMethodError。此外,如果您添加更多管理员类型,它是向前兼容的。

答案 1 :(得分:2)

您可以简单地使用collect,而不是include?any?机制。如果clinic_memberships始终返回一个数组(如果它是例如has_many关联则会执行此操作),您甚至不需要检查它。

def has_membership?(resource, &block)
  return unless resource.user
  resource.user.clinic_memberships.any?(&block)
end

然后可以像

一样调用它
has_membership?(resource, &:portal_admin?)

相当于

has_memberhsip?(resource){|m| m.portal_admin?}

答案 2 :(得分:0)

def is_admin?(resource, kind)
  if resource.user && resource.user.clinic_memberships.any?
    !!resource.user.clinic_memberships.detect { |membership| membership.send("#{kind}_admin?") }
  end
end

如果你没有输入if分支,则返回nil,所以像上面那样做你的条件将产生与显式返回相同的结果,除非......

添加第二个参数并传递:staff或:portal(或“staff”或“portal”)。使用“send”会在运行时评估为“staff_admin?”或“portal_admin?”

使用detect而不是collect + include?如果至少找到一个对象将返回一个对象!!双重否定将其变为真/假结果。

我个人只是这样做,因为那资源.user.clinic_memberships.any?在宏伟的计划中没有实际意义:

def is_admin?(resource, kind)
  !!resource.user.clinic_memberships.detect { |membership| membership.send("#{kind}_admin?") } if resource.user
end

如果你真的试图防止clin_Mmberships为nil,那么你确实需要条件的下半部分,但是放弃“.any?”,否则你会得到一个错误测试?反对零。

答案 3 :(得分:0)

def is_portal_admin?(resource)
  is_admin_of_type?(resource, :portal)
end

def is_staff_admin?(resource)
  is_admin_of_type?(resource, :staff)
end

def is_admin_of_type?(resource, type)
  if (user = resource.user)
    user.clinic_memberships.any? { |ms| ms.send("#{type}_admin?") }
  end
end
  • 检查是否有memberships
  • 是多余的
  • 您可以在条件之后添加|| false,以确保您的method?返回布尔值。
  • 您可以is_admin_of_type?私有。