I have a query object in a rails project which searches a resource with multiple filters (fees, name, specialty, years of experience).
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
The filter methods are private methods removed for brevity.
The call method gives "assignment branch condition is too high" rubocop warning, which makes sense because it does much. How I can refactor it to bypass the rubocop warning?
I saw a few similar questions but none of them solved my problem.
There are plenty of ways to construct scopes in Rails without using reassignment which just the lazy way to do it.
You could make chainable scopes on the the model itself:
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
That will let you call:
Doctor.filter_by_speciality(params[:speciality])
.filter_by_name(params[:name])
# etc
Always returning self or another scope will prevent nil errors.
You can also use .merge
to combine scopes.
Doctor.where(name: 'John').merge(
Doctor.where(specialty: 'pediatrician')
)
So if you start by refactoring the scoped
argument out of those methods you can compose an array of scopes and merge them together:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.