【问题标题】:"Assignment Branch Condition size for call is too high" in rails query objectrails查询对象中的“调用的分配分支条件大小太高”
【发布时间】:2023-04-07 07:25:01
【问题描述】:

我在 Rails 项目中有一个查询对象,它使用多个过滤器(费用、姓名、专业、经验年限)搜索资源。

class SearchDoctors
  attr_accessor :initial_scope, :search_params

  def self.call(initial_scope, search_params)
    new(initial_scope, search_params).call
  end

  def initialize(initial_scope, search_params)
    @initial_scope = initial_scope
    @search_params = search_params
  end


  # Assignment branch condition on call method
  def call
    scoped = filter_by_speciality(initial_scope, search_params[:speciality])
    scoped = filter_by_name(scoped, search_params[:name])
    scoped = filter_by_fees(scoped,
                            search_params[:fees_from],
                            search_params[:fees_to])
    filter_by_years_of_experience(scoped,
                                  search_params[:experience_from],
                                  search_params[:experience_to])
  end
end

为简洁起见,过滤器方法是私有方法。

call 方法给出“赋值分支条件太高”的 rubocop 警告,这是有道理的,因为它做了很多事情。我如何重构它以绕过 rubocop 警告?

我看到了一些类似的问题,但都没有解决我的问题。

【问题讨论】:

    标签: ruby-on-rails ruby rubocop


    【解决方案1】:

    有很多方法可以在 Rails 中构建作用域而不使用重新分配,这只是一种懒惰的方式。

    您可以在模型本身上创建可链接的范围:

    class Doctor < ApplicationRecord
      def self.filter_by_speciality(speciality)
        speciality.present ? self.where(speciality: speciality) : self     
      end
    
      def self.filter_by_name(name)
        name.present ? self.where(name: name) : self     
      end
    end
    

    这会让你打电话:

    Doctor.filter_by_speciality(params[:speciality])
          .filter_by_name(params[:name])
          # etc
    

    始终返回 self 或其他作用域将防止出现 nil 错误。

    您也可以使用.merge 来组合作用域。

    Doctor.where(name: 'John').merge(
      Doctor.where(specialty: 'pediatrician')
    )
    

    因此,如果您首先从这些方法中重构 scoped 参数,您可以组成一个范围数组并将它们合并在一起:

    def call
      # not going to list them all. 
      scopes = [filter_by_speciality(search_params[:speciality]), filter_by_name(search_params[:name])]
      scopes.compact.each_with_object(initial_scope) do |filter, memo|
         memo.merge(filter)
       end
    end
    

    【讨论】:

    • 感谢您的回答。我认为查询对象是隐藏查询并将它们从模型中删除。是这样吗?
    • 可能是。我将查询对象称为“模式视觉”的症状,其中修复比问题更糟糕。 signalvnoise.com/posts/3341-pattern-vision
    猜你喜欢
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 2016-04-13
    • 2019-10-17
    • 2021-06-16
    • 2015-09-05
    • 2022-06-20
    • 1970-01-01
    相关资源
    最近更新 更多