Rails重构冗长where条件:如何优化含重复参数的查询代码?
Rails代码重构:避免重复参数传递
方法1:使用命名占位符简化SQL
Rails支持在SQL查询中使用命名占位符,既能避免重复传参,还能简化日期范围的写法:
prev_month_start = Date.today.prev_month.beginning_of_month prev_month_end = Date.today.prev_month.end_of_month contacts = contacts.where( 'persons.actual_delivery_date BETWEEN :start AND :end OR persons.expected_shipment_date BETWEEN :start AND :end', start: prev_month_start, end: prev_month_end )
通过:start和:end命名占位符,相同参数只需传递一次,同时用BETWEEN替代>=+<=的组合,让SQL更简洁。
方法2:用Arel构建纯Ruby风格查询
借助Rails的Arel接口,完全摆脱手写SQL字符串,逻辑更直观:
prev_month_range = Date.today.prev_month.beginning_of_month..Date.today.prev_month.end_of_month person_table = Person.arel_table contacts = contacts.where( person_table[:actual_delivery_date].in(prev_month_range).or( person_table[:expected_shipment_date].in(prev_month_range) ) )
直接用Ruby范围对象定义日期区间,通过Arel的in和or方法组合条件,全程无需拼接SQL。
方法3:拆分条件后用or组合
把两个日期查询拆成独立条件,再用Rails的or方法合并,可读性拉满:
prev_month_range = Date.today.prev_month.beginning_of_month..Date.today.prev_month.end_of_month actual_delivery_scope = contacts.where(persons: { actual_delivery_date: prev_month_range }) expected_shipment_scope = contacts.where(persons: { expected_shipment_date: prev_month_range }) contacts = actual_delivery_scope.or(expected_shipment_scope)
利用Rails哈希条件语法定义单字段范围查询,再通过or合并两个查询范围,参数仅需定义一次。
内容的提问来源于stack exchange,提问作者Aydar Omurbekov
相关产品推荐
相关产品推荐

