Ruby Science

Extract Method

The simplest refactoring to perform is extract method. To extract a method:

  • Pick a name for the new method.
  • Move extracted code into the new method.
  • Call the new method from the point of extraction.

Uses

Example

Let’s take a look at an example of long method and improve it by extracting smaller methods:

def create
  @survey = Survey.find(params[])
  @submittable_type = params[]
  question_params = params.
    require().
    permit(, , , , )
  @question = @survey.questions.new(question_params)
  @question.submittable_type = @submittable_type

  if @question.save
    redirect_to @survey
  else
    render 
  end
end

This method performs a number of tasks:

  • It finds the survey that the question should belong to.
  • It figures out what type of question we’re creating (the submittable_type).
  • It builds parameters for the new question by applying a white list to the HTTP parameters.
  • It builds a question from the given survey, parameters and submittable type.
  • It attempts to save the question.
  • It redirects back to the survey for a valid question.
  • It re-renders the form for an invalid question.

Any of these tasks can be extracted to a method. Let’s start by extracting the task of building the question.

def create
  @survey = Survey.find(params[])
  @submittable_type = params[]
  build_question

  if @question.save
    redirect_to @survey
  else
    render 
  end
end

private

def build_question
  question_params = params.
    require().
    permit(, , , , )
  @question = @survey.questions.new(question_params)
  @question.submittable_type = @submittable_type
end

The create method is already much more readable. The new build_question method is noisy, though, with the wrong details at the beginning. The task of pulling out question parameters is clouding up the task of building the question. Let’s extract another method.

Replace Temp with Query

One simple way to extract methods is by replacing local variables. Let’s pull question_params into its own method:

def build_question
  @question = @survey.questions.new(question_params)
  @question.submittable_type = @submittable_type
end

def question_params
  params.
    require().
    permit(, , , , )
end

Other Examples

For more examples of extract method, take a look at these chapters:

Next Steps

  • Check the original method and the extracted method to make sure neither is a long method.
  • Check the original method and the extracted method to make sure that they both relate to the same core concern. If the methods aren’t highly related, the class will suffer from divergent change.
  • Check newly extracted methods for feature envy. If you find some, you may wish to employ move method to provide the new method with a better home.
  • Check the affected class to make sure it’s not a large class. Extracting methods reveals complexity, making it clearer when a class is doing too much.

Ruby Science

The canonical reference for writing fantastic Rails applications from authors who have created hundreds.

Work with us to make a new Rails app, or to maintain, improve, or scale your existing app.