The Refactoring
Now that yesterday’s split method is done, I can use pull up method to remove several similar before_filters
. I had to add a declarative method (#model_object
) so each controller can state which model should be used in the finders.
Before
1
2
3
4
|
# app/controller/application_controller.rb
class ApplicationController < ActionController::Base
# ...
end |
# app/controller/application_controller.rb
class ApplicationController < ActionController::Base
# ...
end
1
2
3
4
5
6
7
8
9
10
11
|
# app/controller/documents_controller
class DocumentsController [:index, :new]
private
def find_document
@document = @object = Document.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end |
# app/controller/documents_controller
class DocumentsController [:index, :new]
private
def find_document
@document = @object = Document.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
1
2
3
4
5
6
7
8
9
10
11
|
# app/controller/issue_categories_controller
class IssueCategoriesController :new
private
def find_category
@category = @object = IssueCategory.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end |
# app/controller/issue_categories_controller
class IssueCategoriesController :new
private
def find_category
@category = @object = IssueCategory.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
After
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# app/controller/application_controller.rb
class ApplicationController < ActionController::Base
def find_model_object
model = self.class.read_inheritable_attribute('model_object')
if model
@object = model.find(params[:id])
self.instance_variable_set('@' + controller_name.singularize, @object) if @object
end
rescue ActiveRecord::RecordNotFound
render_404
end
def self.model_object(model)
write_inheritable_attribute('model_object', model)
end
end |
# app/controller/application_controller.rb
class ApplicationController < ActionController::Base
def find_model_object
model = self.class.read_inheritable_attribute('model_object')
if model
@object = model.find(params[:id])
self.instance_variable_set('@' + controller_name.singularize, @object) if @object
end
rescue ActiveRecord::RecordNotFound
render_404
end
def self.model_object(model)
write_inheritable_attribute('model_object', model)
end
end
1
2
3
|
# app/controller/documents_controller
class DocumentsController [:index, :new]
end |
# app/controller/documents_controller
class DocumentsController [:index, :new]
end
1
2
3
4
5
6
7
8
9
10
11
12
|
# app/controller/issue_categories_controller
class IssueCategoriesController :new
private
# Wrap ApplicationController's find_model_object method to set
# @category instead of just @issue_category
def find_model_object
super
@category = @object
end
end |
# app/controller/issue_categories_controller
class IssueCategoriesController :new
private
# Wrap ApplicationController's find_model_object method to set
# @category instead of just @issue_category
def find_model_object
super
@category = @object
end
end
Review
As a result of this refactoring, five controllers were able to throw away their custom method to find an object. This will also let me throw away some custom methods in my plugins that do the exact same thing.
You might notice that IssueCategoryController
is different. It uses the instance variable @category
instead of @issue_category
. By using Ruby’s inheritance I was able to wrap #find_model_object
and set the correct instance variable.
Reference commit