Redmine Refactor #119: Extract Class from NewsController

Now that I’ve refactored many of the standard REST methods in NewsController, I need to work on the non-standard ones. There are two which really bother me, #add_comment and #destroy_comment.

If your controllers have actions that include the name of a different model, there is a good chance that a extract class needs to happen. In this case, I’ll start to extract those methods to a new CommentsController.

Before

1
2
3
4
5
6
7
8
9
10
11
class NewsController < ApplicationController
  def add_comment
    @comment = Comment.new(params[:comment])
    @comment.author = User.current
    if @news.comments < 'show', :id => @news
    else
      show
      render :action => 'show'
    end
  end
end

After

1
2
3
class NewsController < ApplicationController
  # No more add_comment
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CommentsController  :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
  def create
    @comment = Comment.new(params[:comment])
    @comment.author = User.current
    if @news.comments < 'news', :action => 'show', :id => @news
  end
 
  private
 
  # ApplicationController's find_model_object sets it based on the controller
  # name so it needs to be overriden and set to @news instead
  def find_model_object
    super
    @news = @object
    @comment = nil
    @news
  end
 
end

When extracting CommentsController, I also renamed #add_comment to #create. It’s a more descriptive name and will make it easier to setup CommentsController as a REST resource right away. I also had to add a few before_filters and utility methods in order for CommentsController to be fully extracted from NewsController.

I also had to change how the #create method handles unsuccessful comments. It’s not an ideal change, but Redmine’s News pages are embedding the commenting forms directly so it would take some major view refactoring before I can get the user experience (UX) right. For now, I’m going to stay focused on the controllers. That’s where I can make the best improvements.

Reference commit