This episode is for members only

Sign up to access "Building a Notification Preference System in Laravel" right now.

Get started
Already a member? Sign in to continue
Playing
06. Transforming and storing notification preferences

Transcript

00:00
So possibly the most difficult part about this is figuring out how to structure this data within our HTML form to be able to send this to our controller and then sync this up in the database. What we don't want to do is do too much transformation in the back end and make this more complex than it needs to be. Okay now let's just go back to the browser and think about how
00:23
this stuff is laid out. So we've got an individual notification which we can identify individually using an ID and for each of these we basically want to say when we submit this through to the controller method which of these is selected for each of these notifications. So for each of these we kind of want these grouped and then we want really just to send across an array of each of
00:47
these values that have been checked or not and then we want to be able to sync them up in the database. So how do we do this? Well we need to give the input here a name so let's just give this a name of notifications and we're going to use array notation here so we can uniquely identify each of these individual keys and then we want to add on to these the channel type. So in here I'm
01:15
just going to say notification ID and let's give these a value actually so let's just give this a value of on just to demonstrate how this works. Okay so over in our notification controller let's go under our update method bring in our request here we'll be validating this shortly let's just die down on request and get notifications and just see what comes through when we select this. So
01:44
let's choose email and slack for this first one and we'll just choose email for the second one and hit save. Okay so this isn't too useful we've got five and seven which are the notification IDs and these just both say on because I've selected one of these. We know that we're working with slightly more complex data because we have an array of things that could be checked so what we want to
02:07
do is turn this itself into an array by just adding an empty array onto the end here kind of like we would do in php. The value for this is going to be the notification channel type so that'll be email, slack, sms, whatever. So in here we can set the value to the notification channel which remember we are already iterating through here and then overall we're iterating through the notification
02:31
and that's going to be the type. So what's going to happen now is each of these so the first iteration of this will represent let's just remind ourselves email and the second will represent slack. If I choose both of these these two values will be pushed into this array here with this notification ID so we'll basically know what types have been selected in here for the notification
02:56
ID in the list. So this is like a multi-level or multi-dimensional array based on the notification ID and then the data inside of that. Let's try this out and see what it looks like. So let's say email and slack email for this one and obviously we know each of these notifications themselves are exactly the same so we'll just go down to a file is deleted and check both of them. Okay let's hit
03:22
save and see what we've got. So now things start to look a little bit different we've got 5, 7 and 11 which is the IDs for each of the notification types that we have chosen and then inside of these we have an array. So this is really helpful now we know that what we can do based on our database structure that we set up earlier is we can sync up the notification ID which is the key
03:48
that we have over here with the data inside of here which is now an array we can push that to that channel's pivot. So let's go ahead and look at transforming this data so it's easily passed into our notification preferences so we can sync it. The most important thing here is syncing this data rather than just inserting it. Okay let's go over to our notification controller again and
04:15
let's start to plug this data out in a slightly different way. So let's say notifications will assign this. Now what we actually want to do here because we want to do a little bit of transformation on this we're actually going to use the request collect method which will do exactly the same thing as get it will just put this into a Laravel collection for us so we can start to
04:38
transform on it. So let's just take a look at that now on diadump on notifications and have a look and there we go we get exactly the same thing it's just within a collection now so it's a little bit easier for us to transform. So what do we want to do with this let's bring back that diadump and let's go and map this with keys so we're going to use the keys as well as everything else and let's
05:02
create out a long closure for now. What do we get into here? Well we get the channels which is the value and we get the notification id which is the key so this now is going to represent each of the keys that we want to store so we can just return the notification id and then an array with the data we want to insert into the pivot table for our notification user. So let's go back over and
05:31
we're going to say channels and remember we need to do this transformation because although we have an array within the notification id it's not set up in the structure we need for our database so we're basically just changing the structure around here. Let's take a look at what this now looks like so I'm just going to say to array and let's go if we give that a refresh and there we go
05:51
so now this data is in the perfect format for us to go ahead and sync this directly with our user. Let's go ahead and do that now and then we're going to write a couple of tests so we can verify that this data is actually properly getting inserted because we're not going to see this in the UI just yet until we go ahead and fix that up. Okay let's go over and try
06:15
this out so what do we need to do here? Well the first thing I'm going to do is actually just change this over to a short closure there's not really much need for this to be a long closure so what we can do is just take this and we can go ahead and return an array here like this with this data in here and we can take the channels like we did before and the notification id like
06:38
we did before and that's going to do exactly the same thing and give us exactly the same. Now what I can do is just take all of this data here so I'm just going to directly put this inside of request user notification preferences so that's the relationship now we can sync this now by syncing this what it's going to do is it's going to not insert it again and again and again
07:01
that's not what we want we want to sync this data if something in here has been removed it will be removed from our database in that pivot table if something's been added it will add to that pivot table so this is exactly what we want here and then we want to go ahead and just return back. Okay let's go ahead and just check this out we won't see anything in the UI of course because
07:24
we're not outputting anything in the UI but let's just test this out so I'm going to make sure the pivot table here is clear let's go ahead and choose email and slack for the first notification and hit save and let's go over to the database and see what we've got great so we've got notification id of five that looks good project created and if we come over yep sure enough it's been stored
07:44
for my user and we have email and slack now the beauty here is that when we're working with sync even if we do this like this so even if I say well this would be what it would look like by default when we land on this page I'm going to get rid of slack and I'm just going to add email by using sync it's going to detect what data including in them pivot columns has changed
08:06
and it's just going to update it so now you can see that that's just gotten rid of slack and we've got email in here it's not added a new record it's not completely deleted the record it's just synced all this data up and we can do this for as many of the notifications on this page now as we like so just as an example let's go ahead and just select a few random ones here
08:26
hit save go back over and there we go it's stored each of the notification preferences and the channels for each one okay so now that we've done this let's go ahead and write a test just to verify this and then of course if anything changes later on we know it is broken so completely optional but to go ahead and get set up for tests we're going to come over to
08:48
phpunit.xml we're going to uncomment the db connection and the database lines here so we can use sqlite and in-memory database testing I've chosen pest for the testing framework which if we run this we'll go through and run through all of the base tests that we have in Laravel Breeze but we're going to go and create our new test here so we're going to say pest test and we
09:12
are going to test in our controllers and notification controller test so let's load this up so let's go into feature controllers notification controller test obviously this fails because we haven't added anything to it let's start to write a couple of basic tests for this update functionality so we're going to go with the best case scenario here it enables notification
09:38
preferences for a user and then we're going to do the opposite of this and that it actually removes this data as well okay so what do we need to do here well we need to go ahead and create out a basic notification so we're going to use our notification factory to create this out for a notification group remember a notification has to belong to a notification group so we're
10:10
going to go ahead and create that out now what that does is it gives us the opportunity to then go ahead and create out a user send a request through and make sure this gets added so let's go and create out a user here that we want to use to send the request and we're going to add to this test a little bit more in a moment so let's just say user factory we'll keep this really
10:33
basic for now and let's so just say create and then acting as that user we're going to go ahead and send a patch request down to the notifications route that we have just posted to so let's say notification and update and what kind of data do we want to send down here well we want to send the notification data that we dumped a little bit earlier and in here we want to send down the
11:02
notification that we want to add which is going to be this one here that we've just created so we've created that in the factory so let's say notification id and we can just add any channels we want in here so let's say email and slack and let's go ahead and just run this test and see what we get okay let's run this and we get a failure let's just take a look here
11:25
and we have an undefined method notification group okay so for our notification let's create the relationship in here although we're not technically using that with our code it doesn't really matter notification group and also this belongs to notification and group so let's add that in there okay let's go ahead and run our test here we get another
11:54
failure yeah that's just because we don't have a title here so what we can do is we can come over to our notification group factory and we can add in to the definition here a title let's say fake sentence and two okay let's run our test again and yep we get another failure so this time it's the type for the notifications it's a notification factory and for the type here let's say project
12:26
created we'll just fill this in until it actually works so again we've got title let's say title a project was created and there we go great so now we've got a risky test just because we're not asserting anything but all of that data is now getting inserted and this request seems to be working so we want to assert that we have a redirect back so that's what we've
12:52
done within our test let's run that and make sure that works so the request itself is actually working but how do we assert that the actual data has been inserted into the database there's a couple of ways that we could do this we could say assert database has for example we can give the table and all of the data but most of the time i prefer to do is just grab a fresh instance of the
13:12
user which will freshen up all of the data for the user and the relationships and then we can just add an expectation on the user notification preferences to check that it has all of the data that we need so we can say to have count for example one that's a really basic assertion make sure that's been inserted and you can see that that does work and then we could say something
13:36
like get zero so get the first one and make sure the pivot channels have a specific value so we're going to say well we want to make sure these contain email and slack i think we added both of them up there yeah we did so email and slack so basically you just pluck that data out and make sure it contains the channels that we selected when we sent this through okay so now that we
14:00
have done this what can we do to improve this test what we want to make sure is that even if we have an initially attached notification we don't want that to disappear because if we changed up our controller to insert this data for example but that got rid of the other data that we wanted to keep then we'd be in trouble and this test would still pass so what we want to do here is we want
14:25
to create out a user but we want to say that it already has an attached notification so we'll say has attached notification factory and again because we need a group for our factory we just need to say for notification and group and factory like so so we just basically insert a factory a notification already and for this what we can then do is we can go ahead and choose the channels so we can
14:51
choose the pivot data when we insert this as part of our laravel factory so let's just say that the channels here was just email and we want to choose the notification preferences relationship here or it might not be able to figure it out let's rerun that test just make sure that works and that's great so we've already got a notification now inserted what we can now do is send this across
15:16
with the notification payload so we can say user notification preferences we can extract that preference that we have just got and the id and we could maybe change that over so let's change that from email to email and slack and let's insert this one here with just email for example we basically just want to vary this up so now the assertion is going to become we want to make sure
15:48
that the notification that already existed here has changed from just email to email and slack and the new notification that we've added has email so for the first one we want to make sure that that has email and slack and for the second one we want to make sure the pivot channels contains email but doesn't contain so we can say not to contain slack because we're basically
16:16
getting rid of one of them i'll go over what this test is doing in the ui in just a second in case it doesn't make any sense let's just run our test now just make sure that this is all good and yeah of course we just need to update the fact that this should have now two notification counts let's run our test and we get green with six assertions just by doing this we're pretty confident that we
16:39
can update and actually sync this data rather than insert it into the database so let's just go through this so let's imagine that the user already has for some notification email selected that would look like that in the original instance what we're testing for in this test is that we change from email to email and slack so that would be clicking this that doesn't get rid of
17:05
this it doesn't duplicate this it just adds it on and then for the second notification we're choosing that we want email so essentially what this test is doing is it's checking that we can modify an original one or a pre-selected notification but it's also adding one on at the same time so when I hit save here that's exactly what that test is doing assuming we have that data saved in the first
17:29
place okay so we want to do a well we're going to write another test it's pretty much going to be the same thing so we're going to say it disables notification preferences for a user now we already kind of know this works because we know that we've modified this value to email from email to email and slack but it doesn't hurt to create a specific test for this so what I'm actually going to do is
17:57
copy all of this because the majority of the setup here is going to be exactly the same so let's go ahead and paste this in now what do we want to do here well I kind of want to start off with two notification types and I want to remove one of them so let's say count two and for the channels here let's say email and slack but we want to vary this up for each of the notifications that we have
18:20
just inserted so what we can do here is we could say for notification factory so let's pull this up to here we want a count of two but we want to modify the state for each of these so for this we say new sequence now this is just a way of changing the type for each one so the first type is going to be project created as an example and a second one is going to be project deleted so
18:50
we've now got a an initial user with two notification preferences already stored for project created project deleted and both have email and slack as their notifications chosen now what we can do is send a request through to just perhaps get rid of the first one so we either say first or I find it a little bit more helpful actually when we say things like get because
19:19
that just tells us it's the actual first one if we use that one it's going to be the second one so on and so forth so we want to change the first one to have a type of email so that is going to change project created to just email so it's basically just testing whether we can get rid of it so now we can say get zero pivot channels to be or we could say not to contain whichever way
19:48
you wanted to do this email and we can say to have count one like so so what we're now testing just before we run this test what are we testing well let's just have a look we've set up a project created and project deleted so let's just imagine that these two are project created and project deleted with both notifications selected the request that we've sent through is just that we
20:13
want to keep the first one and also modify that to email so we're completely getting rid of the second one we're getting rid of slack there so we're now testing that we can get rid of a complete notification for all channels when we save that that's exactly what we're doing within this test okay let's go ahead and run all of them testing here we get a failure so let's
20:35
just have a look here and yes there's a failure to assert that the array is identical to email and yeah that just needs to be an email array okay let's just go ahead and run that again and there we go so we're pretty confident now that this is working on a sync basis where we're syncing up these notification preferences and not just inserting them or you know overwriting anything
10 episodes1 hr 23 mins

Overview

Need to store advanced notification preferences in your application?

In this course, we cover displaying a matrix of notification groups, types and channels with the ability to sync preferences cleanly and quickly.

Once you’re done, your users will be able to choose what notifications they receive, and how.

Oh, and we’ll write tests to back everything up, look at how to use notification preferences in Notification classes, and how to set defaults for when users register.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!