jjfine
jjfine

Reputation: 877

Putting together array manipulation operations in Ruby

I want to do several operations on an array in a specific order. Each unit of behavior is in it's own method, and I have something like this:

def build_array_of_cool_employees
  employees = fetch_all_employees
  employees = remove_strange_employees_from employees
  employees = add_ideal_employee_to employees
  employees = sort_by_awesomeness employees
end

I was wondering if there's a better way. I feel like I'm missing some feature which could make my code nicer. Am I?

Upvotes: 1

Views: 95

Answers (4)

sawa
sawa

Reputation: 168081

In your case, you should use method chaining. You can subclass Array if you do not want to pollute the Array class.

class Employees < Array
  def self.cool
    fetch_all
    .remove_strange
    .add_ideal
    .sort_by_awesomeness
  end
  def self.fetch_all
    new(...)
  end
  def remove_strange
    ...
    self
  end
  def add_ideal
    ...
    self
  end
  def sort_by_awesomeness
    ...
    self
  end
end

Employees.cool # => ...

Upvotes: 1

Stefan
Stefan

Reputation: 114138

You could create a separate class with chain-able methods. Something like this:

class EmployeeBuilder
  attr_reader :employees

  def initialize
    @employees = []
  end

  def fetch_all
    @employees.push(:qux, :baz, :bar)
    self
  end

  def remove_strange
    @employees.delete(:qux)
    self
  end

  def add_ideal
    @employees.push(:foo)
    self
  end

  def sort
    @employees.reverse!
    self
  end
end

And call it like this:

def build_array_of_cool_employees
  builder = EmployeeBuilder.new
  builder.fetch_all.remove_strange.add_ideal.sort.employees
end

build_array_of_cool_employees
#=> [:foo, :bar, :baz]

Upvotes: 1

Alex.Bullard
Alex.Bullard

Reputation: 5563

It depends on how your methods are implemented. If they modify the original array you could do something like this:

fetch_all_employees.tap do |employees|
  remove_strange_employees_from(employees)
  add_ideal_employee_to(employees)
  sort_by_awesomeness(employees)
end

Note that methods like delete_if or push modify the original array, so if you are using them in the implementation of your methods it should just work.

Upvotes: 0

danmanstx
danmanstx

Reputation: 1712

this might read slightly nicer depending on how you feel about method chaining, but requires array to be a extended, and you then can call your custom methods on the array directly how you see fit. Better yet would be to have an employees list object and then manipulate that, but the idea is similar.

class Array
    def sort_by_awesomeness
        #your sort
    end

    def  add_ideal_employee(cool_employee)
        self.push(cool_employee)
    end 
    def remove_strange_employees(uncool_employees)
        uncool_employees.each do |uncool_employee|
            self.delete(uncool_employee)
        end 
        # return self here to continue the method chaining
        return self
    end
end

def build_array_of_cool_employees
  employees = fetch_all_employees.add_ideal_employee(cool_employee).remove_strange_employees(uncool_employees).sort_by_awesomeness
end

Upvotes: 0

Related Questions