Wednesday, March 19, 2008
Ruby: Replace Temp with Chain
You have methods that can be chained for greater maintainability.
becomes
Motivation
Calling methods on different lines technically gets the job done, but at times it makes sense to chain method calls together and provide a more fluent interface. In the above examples, assigning an expectation to a local variable is only necessary so that the arguments and return value can be specified. The solution utilizing Method Chaining removes the need for the local variable. Method Chaining can also improve maintainability by providing an interface that allows you to compose code that reads naturally.
Mechanics
Suppose you were designing a library for creating html elements. This library would likely contain a method that created a select drop down and allowed you to add options to the select. The following code contains the Select class that could enable creating the example html and an example usage of the select class.
The first step in creating a Method Chained solution is to create a method that creates the Select instance and adds an option.
Next, change the method that adds options to return self so that it can be chained.
Finally, rename the add_option method to something that reads more fluently, such as "and".
mock = Mock.new
expectation = mock.expects(:a_method_name)
expectation.with("arguments")
expectation.returns([1, :array])becomes
mock = Mock.new
mock.expects(:a_method_name).with("arguments").returns([1, :array])Motivation
Calling methods on different lines technically gets the job done, but at times it makes sense to chain method calls together and provide a more fluent interface. In the above examples, assigning an expectation to a local variable is only necessary so that the arguments and return value can be specified. The solution utilizing Method Chaining removes the need for the local variable. Method Chaining can also improve maintainability by providing an interface that allows you to compose code that reads naturally.
Mechanics
- Return self from methods you wish to allow chaining from
- Test
- Remove the local variable and chain the method calls
- Test
Suppose you were designing a library for creating html elements. This library would likely contain a method that created a select drop down and allowed you to add options to the select. The following code contains the Select class that could enable creating the example html and an example usage of the select class.
@options ||= []
end
options << arg
end
end
select = Select.new
select.add_option(1999)
select.add_option(2000)
select.add_option(2001)
select.add_option(2002)
select # => #<Select:0x28708 @options=[1999, 2000, 2001, 2002]>
The first step in creating a Method Chained solution is to create a method that creates the Select instance and adds an option.
select = self.new
select.options << option
select
end
# ...
end
select = Select.with_option(1999)
select.add_option(2000)
select.add_option(2001)
select.add_option(2002)
select # => #<Select:0x28488 @options=[1999, 2000, 2001, 2002]>
Next, change the method that adds options to return self so that it can be chained.
# ...
options << arg
self
end
end
select = Select.with_option(1999).add_option(2000).add_option(2001).add_option(2002)
select # => #<Select:0x28578 @options=[1999, 2000, 2001, 2002]>
Finally, rename the add_option method to something that reads more fluently, such as "and".
select = self.new
select.options << option
select
end
@options ||= []
end
options << arg
self
end
end
select = Select.with_option(1999).and(2000).and(2001).and(2002)
select # => #<Select:0x28578 @options=[1999, 2000, 2001, 2002]>Labels: refactoring, ruby
Comments:
<< Home
I find that this is one of those places where I wish the ruby parser was a little smarter so I could write:
Select.with_option(1999)
.and(2000)
.and(2001)
.and(2002)
rather than:
Select.with_option(1999) \
.and(2000) \
.and(2001) \
.and(2002)
Javascript gets it right after all.
Post a Comment
Select.with_option(1999)
.and(2000)
.and(2001)
.and(2002)
rather than:
Select.with_option(1999) \
.and(2000) \
.and(2001) \
.and(2002)
Javascript gets it right after all.
<< Home




