繁体   English   中英

如何重构方法以降低 RuboCop 的 ABCsize

[英]How to refactor method to lower RuboCop's ABCsize

在我学习 ruby​​ 和 rails 的过程中,我继续安装了 Rubocop。 到目前为止,它对以 ruby​​ 方式重构我的代码有很大帮助,但现在我想我已经被这个无助的案例撞到了墙角。 鉴于以下创建新实体的方法,我正在寻找一种重构它的方法,以使 Rubocop 停止对我大喊大叫:

  1. 线长
  2. 分配分支条件大小(当前为 26.02/15)

我目前唯一能想到的,除了禁用那些 cops ofc,实际上是将模型分成两个较小的模型(比如基本信息和财务)并相应地设置它们,但我的印象是这会将复杂性从创建方法中移出并将其放在其他地方,因为我需要记住创建两个相关实体等。任何提示都非常受欢迎。

def create_store_information(store, meta)
  user = @datasource.user
  user.store_informations.create!(
    name: store['name'],
    description: store['description'],
    status: 1,
    url: store['URL'].downcase,
    store_version: store['version'],
    api_version: store['wc_version'],
    timezone: meta['timezone'],
    currency: meta['currency'],
    currency_format: meta['currency_format'],
    currency_position: meta['currency_position'],
    thousand_separator: meta['thousand_separator'],
    decimal_separator: meta['decimal_separator'],
    price_num_decimals: meta['price_num_decimals'],
    tax_included: cast_to_bool(meta['tax_included']),
    weight_unit: meta['weight_unit'],
    dimension_unit: meta['dimension_unit'],
    ssl_enabled: cast_to_bool(meta['ssl_enabled']),
    permalinks_enabled: cast_to_bool(meta['permalinks_enabled']),
    generate_password: cast_to_bool(meta['generate_password']),
    user: user
  )
end

编辑:根据请求,我附上了从不同的类创建 store_information 的第二个示例。

def create_store_information(store, meta)
  user = @datasource.user
  user.store_informations.create!(
    name: store['id'],
    description: store['name'],
    status: 1,
    url: store['domain'].downcase,
    store_version: '1.0',
    api_version: '1.0',
    timezone: meta['timezone'],
    currency: meta['currency'],
    currency_format: meta['money_format'],
    currency_position: '', # not applicable
    thousand_separator: '', # not applicable, take from user's locale
    decimal_separator: '', # not applicable, take from user's locale
    price_num_decimals: '', # not applicable, take from user's locale
    tax_included: cast_to_bool(meta['taxes_included']),
    weight_unit: nil, # not applicable
    dimension_unit: nil, # not applicable
    ssl_enabled: cast_to_bool(meta['force_ssl']),
    permalinks_enabled: true,
    generate_password: false,
    user: user
  )
end

这只是众多可能性中的 1 个建议。

您可以使用 Ruby 的元编程能力来动态发送方法。 meta对象的字段很容易分配给user.store_informations因为字段匹配 1 为 1。 store对象也是可能的,但它不会那么简单。

您可以将字段移动到类定义中的数组:

CAST_TO_BOOL = %w(
  tax_included
  ssl_enabled
  permalinks_enabled
  generate_password
).freeze

META_FIELDS = %w(
  timezone
  currency
  currency_format
  currency_position
  thousand_separator
  decimal_separator
  price_num_decimals
  tax_included
  weight_unit
  dimension_unit
  ssl_enabled
  permalinks_enabled
  generate_password
).freeze

那么你可以定义一个私有方法来动态设置user.store_informationsmeta字段

private

def set_meta_fields_to_store_information(user)
  META_FIELDS.each do |field|
    if CAST_TO_BOOL.include? field
      user.store_informations.__send__ "#{f}=" { cast_to_bool( meta[field] ) }
      next
    end
    user.store_informations.__send__ "#{f}=" { meta[field] }
  end
end

那么你可以调用该方法:

def create_store_information(store, meta)
  user = @datasource.user
  user.store_informations.new(
    name: store['name'],
    description: store['description'],
    status: 1,
    url: store['URL'].downcase,
    store_version: store['version'],
    api_version: store['wc_version'],
    user: user
  )
  set_meta_fields_to_store_information(user)
  user.save!
end

编辑#2

关于用不同类的对象填充字段;

一种方法是定义一个方法,该方法根据商店的类为您分配字段。 但话又说回来,如果您有数千家不同的商店,这可能不是最佳选择。

class StoreA; end
class StoreB; end
class StoreC; end

然后:

# you could also use dynamic method dispatching here instead:

def set_store_information_to_user(store, user)
  case store
  when StoreA
    assign_store_a_method(store, user)
  when StoreB
    assign_store_b_method(store, user)
  when StoreC
    assign_store_c_method(store, user)
  end
end

private
def assign_store_a_method(store, user); end
def assign_store_b_method(store, user); end
def assign_store_c_method(store, user); end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM