I have a controller class that is large enough to be a bad practice (Rubocop throws this warning: Class definition is too long).
The class has many private methods, all of them calculate paths to redirect to, so it's a controller matter.
How could it be refactored?
Example code:
class PostController
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
# ...
end
# more resources methods
private
def post_params
# ...
end
def post_url(post)
if params['submit-save'] || params['submit-publish']
url_for [:edit, post]
else
url_for [:review, post]
end
end
def next_post_url(post)
next_post = post.find_next
if next_post
url_for [:edit, post]
else
some_path(next_post)
end
end
# some more methods
end
From the discussion on your question, my thought would be to identify if the various private methods that are calculating paths for redirection could belong in a special purpose class that abstracts the various aspects of the path calculation logic or possibly just a module that the controller mixes in. The right answer will depend greatly on exactly what your logic looks like in the various private methods. A simple module is not likely the right approach since you're just moving the code somewhere else to meet an arbitrary metric. Identifying the reason for all the private methods and coming up with a better abstraction is probably the right approach, but there are different patterns that may come into play.
Many of the same patterns discussed in this article will apply to overweight controllers as well as models: 7 Patterns to Refactor Fat ActiveRecord Models
So, extracting conclusions from the comments, I liked these 2 ideas:
I agree that the last word is going to be always from the developer, but if you add a tool like rubocop is to encourage you to write a better code so It makes no sense to me adding rubocop and then disabling some checking.
I would'n use helpers methods either, the reason behind is that a class should have only one responsibility, so it should have only one behaviour. People tend to put methods of all types inside helpers, methods with completely different behaviours which give to that class many different responsibilities. I would just use a helper, if all of its methods have just one and only one purpose.
In your particular case I would be more tempted to extract knowledge into plain classes. Try to identify different behaviours and encapsulate them into classes.
In that case it looks like you have some kind of url builder so a posible solution could be something like :
class PostController
def new
@post = Post.new
end
def create
@post = Post.new(url_builder.post_url)
# ...
end
# more resources methods
private
def url_builder
UrlBuilder.new(self, params)
end
end
class UrlBuilder
def initialize(self, params)
@self = self
@params = params
end
def post_url(post)
if params['submit-save'] || params['submit-publish']
self.url_for [:edit, post]
else
self.url_for [:review, post]
end
end
def next_post_url(post)
next_post = post.find_next
if next_post
self.url_for [:edit, post]
else
some_path(next_post)
end
end
private
attr_reader :self, :params
end
This is not a fully working example as I don't know the entire implementation of your controller, is just a posible solution which will need some adjustments. A couple of things to say about that solution are:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.