Reputation: 877
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
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
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
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
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