我正在制作一个应用程序,其代码的一部分需要许多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
删除它们,以便将其保存到模型中。
知道如何最大限度地减少使用条件或优化条件吗?
答案 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? em>检查并将 delete 中的结果直接写入实例变量。如果密钥不存在,则将为实例变量设置nil
。
最后,我会在row.to_hash.merge!(active: false)
中省略解释标记。没有解释标记的版本不会改变原始阵列并减少意外副作用的机会。您无论如何都要将变量保存到model.attributes
并从 to_hash 方法中删除生成的数组。通常最好使用非改变方法版本,除非您明确要求发生某种效果。