如何用三元表达式/if-else改写Ruby on Rails产品售价取值逻辑?
解决Product按车型获取售价的代码问题
嘿,我来帮你搞定这个售价获取的问题!你的场景是Product和product_varients一对多关联,规则是优先取对应变体的selling_price,变体不存在或售价为空时用产品本身的selling_price。原来的代码没生效,我帮你改成更可靠的if-else和三元表达式写法,还顺便优化了查询效率~
首先分析下原来代码可能的小问题:select {|pv| pv.body_type == vehicle.body_type}.first是把所有变体加载到内存后再筛选,效率偏低;另外如果变体存在但selling_price是nil的话,try(:selling_price)会返回nil,虽然逻辑上会取产品的售价,但可能因为某些边界情况导致不符合预期。下面是优化后的两种写法:
清晰易懂的if-else写法
class Product has_many :product_varients, dependent: :destroy def selling_price_by_body_type(vehicle) # 直接在数据库层面筛选匹配的变体,比内存筛选更高效 matched_variant = product_varients.find_by(body_type: vehicle.body_type) # 先判断变体存在且售价不为空,再返回变体售价,否则用产品本身的售价 if matched_variant && matched_variant.selling_price.present? matched_variant.selling_price else self.selling_price end end end
简洁的三元表达式写法
class Product has_many :product_varients, dependent: :destroy def selling_price_by_body_type(vehicle) matched_variant = product_varients.find_by(body_type: vehicle.body_type) # 用安全导航符&.避免nil调用,再判断售价是否存在,最后用三元表达式分支 matched_variant&.selling_price.present? ? matched_variant.selling_price : self.selling_price end end
关键优化点说明:
- 用
find_by替代select.first:直接在数据库中筛选匹配body_type的变体,减少不必要的数据加载,提升查询性能。 - 增加
present?判断:确保只有变体的selling_price不为nil或空字符串时才使用它,避免出现意外的空值返回。 - 两种写法逻辑一致:if-else更适合需要后续扩展逻辑的场景,三元表达式则更简洁紧凑。
调用方式还是和之前一样:
product.selling_price_by_body_type(@vehicle)
内容的提问来源于stack exchange,提问作者SkRoR
相关产品推荐
相关产品推荐

