chell
chell

Reputation: 7866

How to refactor this code from two methods down to one method

I have the following two methods that are very similar:

            def space_before_element?(start_element)
                element = start_element.previous_element
                until element.nil? ||
                (element.name == start_element.name || "r" && !element.text.empty?)
                  element = element.previous_element
                end
                character = element
                           .text
                           .split(/(\W)/)
                           .compact
                           .reject(&:empty?)
                           .last
                           .last_character \
                           unless element.nil? 

                element.nil? || 
                (character.punctuation? && !character.hyphen? && !character.apostrophe?) || 
                character.spaces? 
              end


            def space_after_element?(start_element)
                element = start_element.next_element
                until element.nil? ||
                (element.name == start_element.name || "r" && !element.text.empty?)
                  element = element.next_element
                end
                character = element
                           .text
                           .split(/(\W)/)
                           .compact
                           .reject(&:empty?)
                           .last
                           .first_character \
                           unless element.nil? 

                element.nil? || 
                (character.punctuation? && !character.hyphen? && !character.apostrophe?) || 
                character.spaces? 
              end

I can't seem to figure out how to make the necessary changes that would allow me to reduce this down to one method.

Still getting my Ruby skills going.

Any help appreciated. Ruby 2.2.3

Upvotes: 0

Views: 127

Answers (1)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

I counted three differences. So, these differences should be explicitly declared:

METHODS = {
  prev: [:previous_element, %i|last last_character|],
  next: [:next_element, %i|first first_character|]
}.freeze

Now we just pass a parameter to the method:

def space_around_element?(start_element, prev_or_next = :prev)
    element = start_element.public_send(METHODS[prev_or_next].first)
    # same code
    character = element
               .text
               .split(/(\W)/)
               .reject(&:empty?)
               .public_send(METHODS[prev_or_next].last.first)
               .public_send(METHODS[prev_or_next].last.last) \
      unless element.nil? 
    # same code
  end

Upvotes: 4

Related Questions