简体   繁体   中英

Rubocop: Assignment Branch Condition size for method is too high. How can I reduce the method?

This block of code:

  def set_conversation
    @conversation = Conversation.find(params[:conversation_id])
                                .match.origin_target.user_id == current_api_user.id ||
                    Conversation.find(params[:conversation_id])
                                .match.end_target.user_id == current_api_user.id
    head :forbidden if @conversation == false
  end

is returning the following rubocop offense:

Metrics/AbcSize: Assignment Branch Condition size for set_conversation is too high. [<1, 17, 5> 17.75/17]

I clearly understand the offense, but I'm having trouble refactoring the code to do the same task without adding too much unnecessary logic, especially because it's barely exceeding the suggested size. As a last resort, I may change the RuboCop config to ignore this block or to increase the limit, but first I want to try to solve it the intended way.

This is quite a complex lookup. One option is to extract this behaviour into a method on Conversation , eg Conversation.lookup(params[:conversation_id], current_api_user)

Another is to introduce a new service layer class or module, eg

LookupConversation.lookup(params[:conversation_id], current_api_user)

(there are likely other names you could choose to better reflect your application's business domain).

Here's a start, which has the added benefit of setting @conversation to a conversation object, rather than a boolean value:

def set_conversation
  @conversation = Conversation.find(params[:conversation_id])

  user_ids = @conversation.match.tap { |m| [m.end_target.user_id, m.origin_target.user_id] }

  head :forbidden if user_ids.include?(current_api_user.id)
end

Although further improvements can probably be made by introducing some meaningfully named method to represent the concept that a user is allowed in a conversation, for example:

class Conversation < ApplicationRecord
  def allowed_for?(user)
    match
      .tap { |m| [m.end_target.user_id, m.origin_target.user_id] }
      .include?(user.id)
  end
end

def set_conversation
  @conversation = Conversation.find(params[:conversation_id])

  head :forbidden conversation.allowed_for?(current_api_user)
end

This also allows Conversation#allowed_for? to be tested in isolation.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM