Ruby 使用地图时代码更透明、更干净

Ruby more transparent and clean code when using map

我有两个简单的方法,可以从 Jira 项目中获取数据,并为用户分配待完成的任务。现在我从 Jira API(time_to_resolution 和 desired_time_to_resolution)获取了 customfields,它看起来不太好,是否有可能以更干净、可读的方式进行?

def assigned_task_list
  assigned_tasks.map do |issue|
    fields = issue.fields

    {
      key: issue.key,
      desired_time_to_resolution: issue.customfield_14777.dig('ongoingCycle', 'remainingTime', 'friendly'),
      time_to_resolution: issue.customfield_10031.dig('ongoingCycle', 'remainingTime', 'friendly'),
      name: fields.dig('assignee', 'name'),
      email: fields.dig('assignee', 'emailAddress'),
      status: fields.dig('status', 'name')
    }
  end
end

下面的assigned_tasks方法:

def assigned_tasks
  project.issues.select do |issue|
    issue.fields.dig('status', 'name') != 'Done' &&
      issue.fields.dig('assignee', 'name')
  end
end

您可以创建多个方法并将逻辑隐藏在其中。

def assigned_task_list
  assigned_tasks.map do |issue|
    {
      key: issue.key,
      desired_time_to_resolution: desired_time_to_resolution(issue),
      time_to_resolution: time_to_resolution(issue),
      name: name(issue),
      email: email(issue),
      status: status(issue)
    }
  end
end

private

def desired_time_to_resolution(issue)
  issue.customfield_14777.dig('ongoingCycle', 'remainingTime', 'friendly')
end

def time_to_resolution(issue)
  issue.customfield_10031.dig('ongoingCycle', 'remainingTime', 'friendly')
end

def name(issue)
  issue.fields.dig('assignee', 'name')
end

def email(issue)
  issue.fields.dig('assignee', 'emailAddress')
end

def status(issue)
  issue.fields.dig('status', 'name')
end

这可能是测试全新 Ruby 2.7 解构又名 pattern matching feature:

的好机会
def assigned_task_list
  assigned_tasks.map do |issue|
    case issue
    in {
      key: key,
      customfield_14777: {
        ongoingCycle: { remainingTime: { friendly: desired_time_to_resolution }}
      },
      customfield_10031: {
        ongoingCycle: { remainingTime: { friendly: time_to_resolution }}
      },
      fields: {
        assignee: { name: name, emailAddress: email },
        status: { name: status }
      }
    }
      {
        key: key, 
        desired_time_to_resolution: desired_time_to_resolution,
        time_to_resolution: time_to_resolution,
        name: name,
        email: email,
        status: status
      }
  end
end

同样适用于 assigned_tasks

您可以创建一个新的 class 来封装 transformation/extraction 逻辑。它将接受 Jira Issue 实例和 return 所需格式的新哈希。

def assigned_task_list
  assigned_tasks.map do |jira_issue|
    IssueTransformer.new(jira_issue).transform
  end
end


# issue_transformer.rb

class IssueTransformer
  attr_reader :jira_issue

  def initialize(jira_issue)
    @jira_issue = jira_issue
  end

  def transform
    {
      key: key,
      desired_time_to_resolution: desired_time_to_resolution,
      time_to_resolution: time_to_resolution,
      name: name,
      email: email,
      status: status
    }
  end

  private

  def key
    jira_issue.key
  end

  def desired_time_to_resolution
    jira_issue.customfield_14777.dig('ongoingCycle', 'remainingTime', 'friendly')
  end

  # etc.
end

现在这可能有点矫枉过正,@Yakov 的建议只是将逻辑包装在私有方法中可能是可行的方法。但是,如果您需要进一步扩展 transformation/extraction 逻辑,像这样(带有自己的单元测试)将是一个好主意,以保持逻辑独立。