索引的圈复杂度太高
Cyclomatic complexity for index is too high
我的控制器中有索引操作:
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
@users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
@users = if params[:sort].to_i == 1
@users.order(full_name: :asc)
else
@users.order(id: :desc)
end
@users = @users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
@users = @users.call('age >= ?', params[:from_date]) if params[:from_date].present?
@users = @users.call('age <= ?', params[:to_date]) if params[:to_date].present?
@users = @users.where(gender: params[:gender]) if params[:gender].present?
@users = @users.includes(:document)
end
但是当我 运行 Rubocop
检查我的代码是否有任何 offense
时。
然后 returns 我犯了两个错误。
app/controllers/users_controller.rb:5:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for index is too high. [11/6]
def index ...
^^^^^^^^^
app/controllers/users_controller.rb:5:3: C: Metrics/PerceivedComplexity: Perceived complexity for index is too high. [13/7]
def index ...
^^^^^^^^^
因此,我将索引操作分为多个操作,例如:
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
search
end
def search
@users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
@users = if params[:sort].to_i == 1
@users.order(full_name: :asc)
else
@users.order(id: :desc)
end
apply_filter
end
def apply_filter
@users = @users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
@users = @users.call('age >= ?', params[:from_date]) if params[:from_date].present?
@users = @users.call('age <= ?', params[:to_date]) if params[:to_date].present?
@users = @users.where(gender: params[:gender]) if params[:gender].present?
@users = @users.includes(:document)
end
这是实现这样的代码的正确方法吗?或者我还能做些什么来改进我的编码结构?
Is this the right way to implement code like this
只要你觉得代码合理清晰就可以了。如果 index
方法是控制器中唯一的方法,那么通过用户搜索的逻辑进行导航不会有问题。
is there anything else i can do to refine my coding structure
其中一个选项是将这两种方法(或更多逻辑)提取到单独的 class/file 中。例如,类似于:
控制器
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
@users = Users::Search.new(@users).call
end
服务
class Users::Search
attr_reader :params, :users
def initialize(users, params)
@users = users
@params = params
end
def search
users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
users = if params[:sort].to_i == 1
users.order(full_name: :asc)
else
users.order(id: :desc)
end
apply_filter(users)
end
def apply_filter(users)
users = users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
users = users.call('age >= ?', params[:from_date]) if params[:from_date].present?
users = users.call('age <= ?', params[:to_date]) if params[:to_date].present?
users = users.where(gender: params[:gender]) if params[:gender].present?
users.includes(:document)
end
end
并且提取的优点之一是这样 class 比控制器方法更容易测试,控制器方法需要请求并为每个测试用例解析响应。
我的控制器中有索引操作:
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
@users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
@users = if params[:sort].to_i == 1
@users.order(full_name: :asc)
else
@users.order(id: :desc)
end
@users = @users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
@users = @users.call('age >= ?', params[:from_date]) if params[:from_date].present?
@users = @users.call('age <= ?', params[:to_date]) if params[:to_date].present?
@users = @users.where(gender: params[:gender]) if params[:gender].present?
@users = @users.includes(:document)
end
但是当我 运行 Rubocop
检查我的代码是否有任何 offense
时。
然后 returns 我犯了两个错误。
app/controllers/users_controller.rb:5:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for index is too high. [11/6]
def index ...
^^^^^^^^^
app/controllers/users_controller.rb:5:3: C: Metrics/PerceivedComplexity: Perceived complexity for index is too high. [13/7]
def index ...
^^^^^^^^^
因此,我将索引操作分为多个操作,例如:
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
search
end
def search
@users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
@users = if params[:sort].to_i == 1
@users.order(full_name: :asc)
else
@users.order(id: :desc)
end
apply_filter
end
def apply_filter
@users = @users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
@users = @users.call('age >= ?', params[:from_date]) if params[:from_date].present?
@users = @users.call('age <= ?', params[:to_date]) if params[:to_date].present?
@users = @users.where(gender: params[:gender]) if params[:gender].present?
@users = @users.includes(:document)
end
这是实现这样的代码的正确方法吗?或者我还能做些什么来改进我的编码结构?
Is this the right way to implement code like this
只要你觉得代码合理清晰就可以了。如果 index
方法是控制器中唯一的方法,那么通过用户搜索的逻辑进行导航不会有问题。
is there anything else i can do to refine my coding structure
其中一个选项是将这两种方法(或更多逻辑)提取到单独的 class/file 中。例如,类似于:
控制器
def index
authenticate_admin!
@users = User.paginate(per_page: 25, page: params[:page])
if params[:list_type].to_i == 2 # => Pending mentors
@users = @users.where(documents: { is_verified: 0 }, user_type: 0, profile_status: 1)
elsif params[:list_type].to_i == 1 # => approved listing
@users = @users.where(documents: { is_verified: 1 }, user_type: 0) if params[:user_type].to_i.zero? # => Mentor
@users = @users.where(user_type: 1) if params[:user_type].to_i == 1 # => mentee
end
@users = Users::Search.new(@users).call
end
服务
class Users::Search
attr_reader :params, :users
def initialize(users, params)
@users = users
@params = params
end
def search
users = @users.where('full_name LIKE ?', "%#{params[:search]}%") if params[:search].present?
users = if params[:sort].to_i == 1
users.order(full_name: :asc)
else
users.order(id: :desc)
end
apply_filter(users)
end
def apply_filter(users)
users = users.profession.where(id: params[:profession_ids]) if params[:profession_ids].present?
users = users.call('age >= ?', params[:from_date]) if params[:from_date].present?
users = users.call('age <= ?', params[:to_date]) if params[:to_date].present?
users = users.where(gender: params[:gender]) if params[:gender].present?
users.includes(:document)
end
end
并且提取的优点之一是这样 class 比控制器方法更容易测试,控制器方法需要请求并为每个测试用例解析响应。