Rubocop 声明太多 'if' 声明
Rubocop claims for too many 'if' statements
我正在使用 Rubocop 测量 Rails 应用程序的代码。这是我的代码:
def ratings_treatment
if @rating.advertise_id
advertise = Advertise.find(advertise_id)
rating_average(advertise)
elsif @rating.product_id
product = Product.find(product_id)
rating_average(product)
elsif @rating.combo_id
combo = Combo.find(combo_id)
rating_average(combo)
else
establishment = Establishment.find(@rating.establishment_id)
rating_average(establishment)
end
end
它没有通过关于 if
的测试。声称有太多if
语句。
我考虑过将代码拆分为一些检查器方法,但想知道是否有更好的方法来获得良好的指标并仍然编写出良好的代码。
我认为您可以使用 switch 语句为 rating_average
:
分配参数
def ratings_treatment
average = case
when @rating.advertise_id then Advertise.find(advertise_id)
when @rating.product_id then Product.find(product_id)
when @rating.combo_id then Combo.find(combo_id)
else Establishment.find(@rating.establishment_id)
end
rating_average average
end
尽管 Rubocop 会抱怨
Style/EmptyCaseCondition: Do not use empty case condition, instead use
an if expression
您还可以简化您的 if 表达式:
def ratings_treatment
average = if @rating.advertise_id
Advertise.find advertise_id
elsif @rating.product_id
Product.find product_id
elsif @rating.combo_id
Combo.find combo_id
else
Establishment.find @rating.establishment_id
end
rating_average average
end
如果您的 @rating
设置了关联,那么您可以说:
def ratings_treatment
obj = @rating.advertise || @rating.product || @rating.combo || @rating.establishment
rating_average(obj)
end
甚至:
def ratings_treatment
rating_average(@rating.advertise || @rating.product || @rating.combo || @rating.establishment)
end
或者也许是一些奇特的东西(并且只对四个分支杀伤力过大):
def ratings_treatment
rating_average(
%w[advertise product combo establishment].lazy.map { |m| @rating.send(m) }.find(&:present?)
)
end
或者甚至:
def rated_object
to_result = ->(m) { @rating.send(m) }
%w[advertise product combo establishment]
.lazy
.map(&to_result)
.find(&:present?)
end
def ratings_treatment
rating_average(rated_object)
end
我什至建议像上面的 rated_object
方法这样的东西确实应该是 @rating
上的方法。您应该能够对已评级的事物进行评级,而无需手动遍历所有可能性。
你甚至可以将 lazy.map...
的内容修补到 Enumerable
中,如果你想要 Enumerable
中的某些东西一直表现得像 e.m1 || e.m2 || e.m3 || ...
(在那里,做到了)短路。
虽然我不知道 Rubocop 会对这些恶作剧做出什么反应。
这是一个经典的风格违规案例,它有更深层次的根本原因,即建模问题。在您的情况下,看起来您实际想要实现的是 polymorphic association。如果您将 Rating
更改为:
# app/models/rating.rb
class Rating < ApplicationRecord
belongs_to :rateable, polymorphic: true
end
您可以让 Rating
与任意数量的事物相关,只需将其添加到关联的另一端:
# app/models/product.rb
class Product < ApplicationRecord
has_many :pictures, as: :rateable
end
你原来的方法,如果还需要的话,变成:
def ratings_treatment
rating_average(@rating.rateable)
end
我正在使用 Rubocop 测量 Rails 应用程序的代码。这是我的代码:
def ratings_treatment
if @rating.advertise_id
advertise = Advertise.find(advertise_id)
rating_average(advertise)
elsif @rating.product_id
product = Product.find(product_id)
rating_average(product)
elsif @rating.combo_id
combo = Combo.find(combo_id)
rating_average(combo)
else
establishment = Establishment.find(@rating.establishment_id)
rating_average(establishment)
end
end
它没有通过关于 if
的测试。声称有太多if
语句。
我考虑过将代码拆分为一些检查器方法,但想知道是否有更好的方法来获得良好的指标并仍然编写出良好的代码。
我认为您可以使用 switch 语句为 rating_average
:
def ratings_treatment
average = case
when @rating.advertise_id then Advertise.find(advertise_id)
when @rating.product_id then Product.find(product_id)
when @rating.combo_id then Combo.find(combo_id)
else Establishment.find(@rating.establishment_id)
end
rating_average average
end
尽管 Rubocop 会抱怨
Style/EmptyCaseCondition: Do not use empty case condition, instead use an if expression
您还可以简化您的 if 表达式:
def ratings_treatment
average = if @rating.advertise_id
Advertise.find advertise_id
elsif @rating.product_id
Product.find product_id
elsif @rating.combo_id
Combo.find combo_id
else
Establishment.find @rating.establishment_id
end
rating_average average
end
如果您的 @rating
设置了关联,那么您可以说:
def ratings_treatment
obj = @rating.advertise || @rating.product || @rating.combo || @rating.establishment
rating_average(obj)
end
甚至:
def ratings_treatment
rating_average(@rating.advertise || @rating.product || @rating.combo || @rating.establishment)
end
或者也许是一些奇特的东西(并且只对四个分支杀伤力过大):
def ratings_treatment
rating_average(
%w[advertise product combo establishment].lazy.map { |m| @rating.send(m) }.find(&:present?)
)
end
或者甚至:
def rated_object
to_result = ->(m) { @rating.send(m) }
%w[advertise product combo establishment]
.lazy
.map(&to_result)
.find(&:present?)
end
def ratings_treatment
rating_average(rated_object)
end
我什至建议像上面的 rated_object
方法这样的东西确实应该是 @rating
上的方法。您应该能够对已评级的事物进行评级,而无需手动遍历所有可能性。
你甚至可以将 lazy.map...
的内容修补到 Enumerable
中,如果你想要 Enumerable
中的某些东西一直表现得像 e.m1 || e.m2 || e.m3 || ...
(在那里,做到了)短路。
虽然我不知道 Rubocop 会对这些恶作剧做出什么反应。
这是一个经典的风格违规案例,它有更深层次的根本原因,即建模问题。在您的情况下,看起来您实际想要实现的是 polymorphic association。如果您将 Rating
更改为:
# app/models/rating.rb
class Rating < ApplicationRecord
belongs_to :rateable, polymorphic: true
end
您可以让 Rating
与任意数量的事物相关,只需将其添加到关联的另一端:
# app/models/product.rb
class Product < ApplicationRecord
has_many :pictures, as: :rateable
end
你原来的方法,如果还需要的话,变成:
def ratings_treatment
rating_average(@rating.rateable)
end