Playlistr: Albums
Let's add an Album
feature to our application and introduce some new ideas.
Albums
Let's start with another simple CRUD
feature. This time to create, read, update and delete an Album
in our application. We're going to introduce a few new ideas with this one.
This time we'll use qb
inside our commandbox-migrations
script rather than raw SQL
.
Migrate Create
If you remember, we created our commandbox-migrations
script in the terminal. We can do it again with migrate create albums
With the script template we can add our qb
functions to build our table schema.
With qb
we have access to closure methods that can create and drop a table as well as add columns definitions. We pass the schema
from qb
into our up()
and down()
methods to give us access to the features of qb
.
The create()
closure takes the name of the table we want to create, "albums", and a function to define the columns in that table. The increments()
method adds an auto-incrementing integer primary key and string()
adds a varchar(255)
string column to the table.
In the down()
method we'll use drop()
to delete our "albums" table.
Album.cfc (Model)
This is the same as the Artist
entity and saved as models/Album.cfc
index.cfm & createUpdate.cfm (Views)
These are also the same as those for the Artist
.
Next we create our Album
service and handler.
Service & Handler
Album Service
Now let's introduce the idea of interacting with our database via a Service component. Add the file models/AlbumService.cfc
to your webroot. The start of this Service component should start by injecting WireBox
and include a simple init()
constructor method.
component {
property wirebox inject="wirebox";
public AlbumService function init() {
return this;
}
}
Now we can add new methods to build out the functionality to interface with our database using Quick
features.
getByID()
public Album function getByID( required any id) {
return wirebox.getInstance( "Album" )
.findOrFail( id );
}
This should look similar to a portion of the update()
action from the Artists
handler.
getAll()
public array function getAll() {
return wirebox.getInstance( "Album" )
.orderby( "id" )
.get();
}
Once again this should look familiar to a portion of the index()
action. The get()
method returns the collection back as an array.
create()
public Album function create( required struct values ) {
return wirebox.getInstance( "Album" )
.create( values );
}
Another similar method. This time we take in a structure of the name/value pairs and pass that on to populate a new row in our database.
update()
public void function update( required any id, required struct values ) {
getByID( id )
.update( values );
}
Here we chain the update()
onto the end of the getByID()
method we wrote earlier and pass on the structure of names/values to update an existing row in our database.
delete()
public void function delete( required any id ) {
getByID( id )
.delete();
}
Similar to update()
, we chain to the end of getByID()
to delete an existing row from our database.
Album Handler
With our new AlbumService
we can simplify our handler. So first create your handler handlers/Albums.cfc
and start with:
component extends="coldbox.system.EventHandler" {
property AlbumService inject="AlbumService";
}
We've added property AlbumService inject="AlbumService";
to the component pseudo constructor to inject the AlbumService
into the handler using the WireBox
convention.
Action: index()
function index( event, rc, prc ) {
prc.albums = AlbumService.getAll();
if( prc.albums.len() == 0 ) {
relocate( "albums.create" );
}
}
We capture all the Albums
into the variable prc.albums
for our view with the getAll()
method in the AlbumService
component but bounce the visitor onto the create action if none are returned.
Action: create()
This is the same as Artists
.
Action: createAction()
function createAction( event, rc, prc ) {
param rc.name = "";
AlbumService.create( {
name: rc.name
} );
relocate( "albums" );
}
This is similar to the Artists
action but it now uses the AlbumService
to create the database row.
Action: update()
function update( event, rc, prc ) {
param rc.id = "";
var album = AlbumService.getByID( rc.id );
prc.name = album.getName();
prc.action = "Update";
prc.formAction = "albums.updateAction";
event.setView( "albums/createUpdate" );
}
Once again this is similar to the Artists
action but it now uses the AlbumService
to get our Album
for updating.
Action: updateAction()
function updateAction( event, rc, prc ) {
param rc.id = "";
param rc.name = "";
AlbumService.update( rc.id, {
name: rc.name
} );
relocate( "albums" );
}
Again, like the Artists
action we use the AlbumService
to update our Album
by passing it the id
and name/value structure of the columns to be updated.
Action: delete()
function delete( event, rc, prc ) {
param rc.id = "";
AlbumService.delete( rc.id );
relocate( "albums" );
}
Finally the delete()
action uses the AlbumService
to removed the selected row from the database.