优化' if else'铁轨的条件

时间:2018-04-12 13:11:42

标签: ruby-on-rails ruby

我正在制作一个应用程序,其代码的一部分需要许多if .. else条件:

   if @model_name == "Style"
        if row.include? ('colors')
          colors = row['colors'].split(';')
          model.style_colors.concat Color.where('code IN (?)', colors).map {|i| i.id.to_s }
          row.delete('colors')
        end

        if row.include? ('gender') and row.include? ('garments')
          @garments = row['garments']
          @gender = row['gender']


          row.delete('garments')
          row.delete('gender')
        end

        if row.include? ('sports')
          @sports = row['sports']

          row.delete('sports')
        end

        if row.include?('decoration_packages')
          @decorations_packages = row['decoration_packages']

          row.delete('decoration_packages')
        end

        model.attributes = row.to_hash.merge!(active: FALSE)
      else
        model.attributes = row.to_hash
      end

我需要创建row哈希对象来访问子类,然后从row删除它们,以便将其保存到模型中。

知道如何最大限度地减少使用条件或优化条件吗?

3 个答案:

答案 0 :(得分:3)

这里有一些优化......

row.include? ('gender') and row.include? ('garments')

可以实现为

['gender', 'garments'].all?{|x| row.include?(x)}
@garments = row['garments']
row.delete('garments')

可以实现为

@garments = row.delete('garments')

你实际上可以把很多这些压在一条线上:

if row.include? ('sports')
  @sports = row['sports']
  row.delete('sports')
end

可能是

@sports = row.delete('sports') if row.include? ('sports')

还值得考虑:

  • 您是否需要删除'行'?中的值?你能找到这个值吗?
  • 你想在这做什么?看起来你正在将哈希拉入实例变量......这基本上就是ActiveRecord所做的。你能用这些属性创建一个模型,然后用这种方式调用它吗?

    Style.new(row) 
    

答案 1 :(得分:0)

if @model_name == "Style"
  if row.include?('colors')
    model.style_colors.concat(
      Color.where(code: row.delete('colors').split(';')).pluck(:id).map(&:to_s)
    )
  end
  if row.include?('gender') and row.include?('garments')
    @garments = row.delete('garments')
    @gender = row.delete('gender')
  end
  if row.include?('sports')
    @sports = row.delete('sports')
  end
  if row.include?('decoration_packages')
    @decorations_packages = row.delete('decoration_packages')
  end
  model.attributes = row.to_hash.merge!(active: false)
else
  model.attributes = row.to_hash
end

答案 2 :(得分:0)

我会用你当前的代码做这样的事情:

if @model_name == "Style"
  row_key_set = row.keys.to_set

  if row.include? 'colors'
    colors = row['colors'].split(';')
    color_ids = Color.where(code: colors).pluck(:id)
    model.style_colors.concat(color_ids.map(&:to_s))
  end

  if row_key_set >= Set['gender', 'garments']
    @garments = row.delete('garments')
    @gender = row.delete('gender')
  end

  @sports = row.delete('sports')
  @decorations_packages = row.delete('decoration_packages')

  model.attributes = row.to_hash.merge(active: false)
else
  model.attributes = row.to_hash
end
  • 您可以使用Color.where('code IN (?)', colors)而不是Color.where(code: colors)

  • 您可以使用pluck.map {|i| i.id.to_s })来获取颜色ID数组,而不是使用.pluck(:id)。这也使得查询更快,因为只从数据库中取出ID而不是整个记录。

  • 我个人喜欢使用sets检查另一组中是否存在多个值。出于这个原因,我创建了row_key_set变量row.keys.to_set。现在,您可以通过检查密钥集是否大于或等于另一个集合(因此是超集)来轻松检查哈希中是否存在某些密钥。 row_key_set >= Set['gender', 'garments']只需一次检查即可将其删除,但如果您有多次检查,这可能是值得的。我也发现以这种方式编写的代码也更具可读性,但这只是个人差异。

  • 您无需检查哈希上是否存在密钥,documentation告诉我们以下内容:

      

    删除键值对并返回其键等于 hsh 中的值。如果找不到密钥,则返回 nil

    这意味着您可以省略 include?检查并将 delete 中的结果直接写入实例变量。如果密钥不存在,则将为实例变量设置nil

  • 最后,我会在row.to_hash.merge!(active: false)中省略解释标记。没有解释标记的版本不会改变原始阵列并减少意外副作用的机会。您无论如何都要将变量保存到model.attributes并从 to_hash 方法中删除生成的数组。通常最好使用非改变方法版本,除非您明确要求发生某种效果。