我正在使用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
语句太多了。
我想过将代码拆分成一些检查器方法,但是想知道是否有更好的方法来获得良好的指标并仍然编写好的代码。
答案 0 :(得分:2)
我认为您可以使用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:不要使用空案例条件,而是使用 一个if表达式
您还可以简化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
答案 1 :(得分:2)
如果您的@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会对这些恶作剧做些什么。
答案 2 :(得分:0)
这是一种典型的违反风格的案例,它具有更深层次的根本原因,即建模问题。在您的情况下,看起来您实际想要实现的是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