【问题标题】:Ruby method refactor multi line assignment to pass RuboCopRuby 方法重构多行赋值以通过 RuboCop
【发布时间】:2023-06-10 20:04:01
【问题描述】:

我一直在尝试调整这个设置复杂分配的方法,我正在寻找其他选项来让这个函数通过警察。

有人有什么想法可以为我指明正确的方向吗?

现在,我正在修补两个内部 .map 调用。

失败的警察

Assignment Branch Condition size for parse_items is too high. [24.08/15]
  def parse_items
Avoid multi-line chains of blocks.
    end.compact.map do |opt|

问题代码

  def parse_items
    options = parse_relationships
    options = options.select { |opt| opt['type'] == 'product_options' }
    options.map do |opt|
      parse_included.detect { |x| x['id'] == opt['id'] }
    end.compact.map do |opt|
      {
        group_id: @payload['id'],
        originator_id: opt['id'],
        price: opt['attributes']['price'],
        description: opt['attributes']['name'],
        exp_quantity: opt['attributes']['quantity'].to_i,
        title: parse_attributes['name'],
        image_originator_url: 'image_for_product',
        updated_at: timestamp
      }
    end
  end

辅助方法

  private

  def parse_data
    @payload['data']
  rescue
    []
  end

  def parse_included
    @payload['included']
  rescue
    []
  end

  def parse_attributes
    @payload['data']['attributes']
  rescue
    []
  end

  def parse_relationships
    @payload['data']['relationships']['options']['data']
  rescue
    []
  end

  def timestamp
    Time.parse(parse_attributes['updated_at'])
  end

更新错误

在规范中:Failure/Error: SELECT = ->(opt) { opt['type'] == 'product_options' } 的参数数量错误(给定 2,预期为 1)

parse_items 的分配分支条件大小太高。 [17/15]

更新代码

  SELECT = ->(opt) { opt['type'] == 'product_options' }
  MAP = ->(opt) { parse_included.detect { |x| x['id'] == opt['id'] } }
  def parse_items
    parse_relationships.select(&SELECT).map(&MAP).compact.map do |opt|
      {
        group_id: @payload['id'],
        originator_id: opt['id'],
        price: opt['attributes']['price'],
        description: opt['attributes']['name'],
        exp_quantity: opt['attributes']['quantity'].to_i,
        title: parse_attributes['name'],
        image_originator_url: 'image_for_product',
        updated_at: timestamp
      }
    end
  end

【问题讨论】:

  • 在这个方法周围加上# rubocop:disable ... / # rubocop:enable ...。 Rubocop 建议很好,但她的建议并非一成不变。
  • 我明白了,这有点简单。我宁愿看看是否有不同的方法来实现这一点。

标签: ruby ruby-on-rails-4 rubocop ruby-style-guide


【解决方案1】:

我能够对其进行重构,使其更加清洁并通过所有警察!万岁!

  def parse_items
    assign_item_attributes(select_included_option(select_item_options(parse_relationships['options']['data'])))
  end

  def select_included_option(options)
    options.map do |opt|
      parse_included.detect { |x| x['id'] == opt['id'] }
    end
  end

  def assign_item_attributes(options)
    options.compact.map do |opt|
      {
        group_id: @payload['id'],
        originator_id: opt['id'],
        price: opt['attributes']['price'],
        description: opt['attributes']['name'],
        exp_quantity: opt['attributes']['quantity'].to_i,
        title: parse_attributes['name'],
        image_originator_url: parse_image,
        updated_at: parse_timestamp
      }
    end
  end

  def select_item_options(options)
    options.select { |opt| opt['type'] == 'product_options' }
  end

【讨论】:

  • 这段代码现在看起来像是用 Ruby 语法编写的 FORTRAN。您刚刚使用 Rubocop Satistaction Time Machine 飞回了 40 年前。我们(希望)已经结束了过程式编程的时代,这段代码是其中最糟糕的例子之一(assign_item_attributes(select_included_option(select_item_options(parse_relationships['options']['data'])))。)我投了反对票,因为与你以前的代码相比,它是一个巨大的倒退。
  • 我与另一位资深人士合作,并被告知这是完全可以接受的。虽然这可能不是您个人的偏好,但这并不意味着它不准确,更不用说在 Ruby 中不常见了。你的回答从来没有奏效,也没有通过警察,所以它不能被接受。