Masonite Coding Tip: Abstracting Recurring Controller Code
Joseph Mancuso
Posted on August 1, 2018
Introduction
If you are not familiar with Masonite then you should checkout the GitHub repo.
When developing with Masonite you may notice, if you are not consciously avoiding it, that you have some duplication in your controller logic. In this tutorial we will walk through how to abstract your code a bit inside your controller to make it really clean.
Controller Constructor
If you are not aware of it yet, probably because you skipped over that section in the documentation, you can put anything you need to in a controller constructor. For example if we have code like this:
from app.League import League
class Controller:
def show(self, Request):
return Request.redirect_to('settings.plans')
def store(self, Request):
league = League.find(Request.param('id'))
league.name = Request.input('name')
league.save()
return Request.redirect_to('settings.plans')
We can abstract the Request
object out and into the controller constructor like so:
from app.League import League
class Controller:
def __init__(self, Request):
self.request = Request
def show(self):
return self.request.redirect_to('settings.plans')
def store(self):
league = League.find(self.request.param('id'))
league.name = self.request.input('name')
league.save()
return self.request.redirect_to('settings.plans')
You might find this a bit more of a cleaner approach and a bit more DRY since we only are worrying about a single line for our Request
object.
Repetitive Model Finding
After a while you will realize that you have some code that looks like this:
from app.League import League
class LeagueController:
def __init__(self, Request, View):
self.request = Request
self.view = View
def show(self):
league = League.find(self.request.param('id'))
return self.view('league/show', {'league': league})
def store(self):
league = League.find(self.request.param('id'))
league.name = self.request.input('name')
league.save()
return self.request \
.redirect_to('league.show', {'league': league})
def delete(self):
league = League.find(self.request.param('id'))
league.delete()
return self.request \
.redirect_to('discover')
Notice here that every single method has the same exact code for fetching the league by id and is using it in different ways. We can simply get around this by throwing that in the constructor as well:
from app.League import League
class LeagueController:
def __init__(self, Request, View):
self.request = Request
self.view = View
self.league = League.find(self.request.param('id'))
def show(self):
return self.view('league/show', {'league': self.league})
def store(self):
self.league.name = self.request.input('name')
self.league.save()
return self.request \
.redirect_to('league.show', {'league': self.league})
def delete(self):
self.league.delete()
return self.request \
.redirect_to('discover')
This actually cleans the code up quite a bit and it makes sense that if all the logic is going to be working with a single league then to have the constructor set it on the controller.
If you want to explore Masonite a bit more be sure to click that link and give a star or join the Slack channel.
Posted on August 1, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.