Episode Transcript
Available transcripts are automatically generated. Complete accuracy is not guaranteed.
Michael (00:00):
Hey. I am Michael
Dyrynda.
Jake (00:02):
And I'm Jake Bennett. Oh,
yeah.
Michael (00:08):
And this is episode 162
of the North Meet South web
podcast.
Jake (00:16):
How many times do I have
to do this before I learn my
lesson? Every time I open a canlike that, I get it all over my
keyboard and it's just a mess.So what in the world? This is
swoon peach tea. I actuallymessaged Aaron, and said he
should he should try this.
He should,
Michael (00:36):
I think I think the way
that it works is that you have
to send him a case of it.
Jake (00:42):
You have
Michael (00:42):
to ship
Jake (00:43):
it to his house. Right
now?
Michael (00:44):
Yeah.
Jake (00:45):
Is that what he said? Like
so in order for him to drink a
soda on his oh, Siri is. Siri istalking to me. So so he he wants
me to send him a case? It's no.
I don't think it's it's
Michael (00:59):
He doesn't want you to.
That's what happened after he
after he put the first episodeout, and he put, you know, his
his office address into theInternet. People started sending
him cases of various, sparklingwaters. So Aaron, if you're
listening to this
Jake (01:16):
If it was only that easy,
he doesn't listen to the show.
Let's be real.
Michael (01:21):
He's a man of the
people.
Jake (01:22):
Dude, dude barely has
enough time to record all the
podcasts that he's on, much lesslisten to podcasts. Pretty sure
the dude doesn't listen to us.
Michael (01:31):
I feel like he records
a lot of podcasts, because I
just saw, like, he posted a linkto the one that he did with
Glauber from, Terso back inJune, and it's the first I'm
seeing anything of it. So
Jake (01:46):
yeah. I know. He's
everywhere. The dude is
everywhere.
Michael (01:50):
I mean, when it when it
is your full time job to create
content, I suppose it makes it abit easier when your entire 9 to
5 is content creation than for,like, you and I who are doing
this in our lunch breaks andafter the kids are in bed and
things like that.
Jake (02:04):
No. For sure. I think
that's definitely true. I mean,
let's be real. I I'm stoked forhim.
I mean, he's done the thing is,like, it's not like he's a slime
bag, and he's just, like,getting on the shows. I mean,
the people reason people havehim on the show is because he's
a genuinely really nice guy, areally good, a really good,
guest because he's great attalking and he's interesting and
he's funny. Mhmm. And thequality of the content that he
(02:27):
puts out is next level. Like, soif you saw the new the Postgres,
trailer thing, Masteringpostgres, I mean, it looks like
a trailer for, like, a album orsomething.
It's Yeah. Incredible. Like, theamount of effort and work that
he puts into this. And then hisfriend Steve as well. Right?
TriHard Studios, both of themtogether. It's just incredible
(02:47):
stuff, and so, you know, good onhim. I'm glad it's going well
for him. You'd hate to seesomebody put in all that effort
and then fail. Yeah.
I'm really glad that people arerecognizing it for for what it
is and, you know, rewarding him,I guess, quote, unquote. And I
mean, maybe not, like,monetarily, but, like, rewarding
him with, like, you know,distribution, essentially.
Getting him on the show Oh,yeah. Getting him in front of
other people, you know.
Michael (03:06):
Well, I messaged him
this morning, because I woke up
my entire Twitter timeline. Itwas just, like, his face over
and over again. Everyone just,like, sharing, retweeting, quote
tweeting, him reposting, like,everyone saying, you know, how
how good this this video looks.I think I watched it about 4 or
5 times.
Jake (03:26):
I I watched it once, and
then I messaged him. I was like,
dude, I think it was fire. Itwas awesome. So good. So
Michael (03:34):
I said, is there any
concern? Is there any concern
over using Frank Sinatra? Like,what's what's the worst here?
And I think we both decided thatthe worst would be that they
get, like, a cease and desist,and they would just have to tear
the video down. But at thatpoint, the market
Jake (03:47):
change the music. Everyone
knows exactly. They've gotten
the exposure for it. Yeah. Yep.
Yep. Really good. I mean, thevideo call I mean, like, the I I
wonder who I shot it on. I mean,he had to set all those shots up
by himself. It's not like he hasan assistant more running around
in his office.
Michael (04:02):
They, you know, someone
Honestly they did. Someone
someone that did he did havesomeone come out. I think he
tweeted about it last week.
Jake (04:09):
So Okay.
Michael (04:10):
And, like, we're just
we're just feeding that machine
right now. We're just talkingabout his content creation
business, and Yeah. You shouldall check out, what is it,
mastering postgres.com orsomething like that. So
Jake (04:20):
Who knows? I don't have
any idea. Yeah.
Michael (04:23):
I've never used
Postgres before, but I think I
think between between thiscourse and Laravel Cloud having
serverless Postgres by defaultalthough, I think Tyler did say
in his q and a that that theyplan to have MySQL available on
launch. But I think betweenthose two things, there is a
good chance that there is gonnabe a lot lot more Laravel
(04:44):
developers in particular lookingat Postgres in the coming
months.
Jake (04:48):
Yeah. Sure. Why not? I
mean, only thing is I don't know
anything about it. That's theonly limiting factor for me.
But, I mean, if you're using allthe take care
Michael (04:56):
of that.
Jake (04:56):
I was gonna say if you're
using the grammar without, like,
eloquent, it doesn't reallymatter. I mean, it's just, you
know, it's just another driver,so who cares? But, anyway, yes.
No. It's, I'm glad for him.
I'm glad for him. It's it's goodstuff. There was something else
I was gonna talk about regardingthat, but don't remember what it
was. So no worries. K.
(05:18):
Couple things I would love totalk to you about today. Yeah.
Number 1, I would love to talkto you about, tenancy in Narwhal
and talk about storing files pertenant in a segmented location.
Let's talk about that. I thinkthat's interesting, and I think
(05:38):
it's something it's a challengewe're trying to solve right now.
I also wanna talk about an I'mpolicy that uses the username of
an I'm user to segment thepermissions, which I really,
really like and I can share intoGistelog. It's something that
we've used recently, and I sortof just stumbled across. I was
like, I really like thatpattern, so I'm gonna do that.
(06:00):
So we should talk about that.And then you had something
recently that you were messingwith, in you talked about this
in cash money.
Cash money, cash oh, you knowwhat else I wanna talk about is,
testing batches.
Michael (06:16):
Thatches. Yeah. That
looks that looks gnarly. What
you
Jake (06:19):
It is a bit it is a bit
gnarly. Yeah. Yeah. But, no. I
think I think we should talkabout that a little bit.
And then what did you have? Youhad something the other day you
were talking about, and I waslike, oh, this makes good sense.
Michael (06:31):
Talking about enums. Is
that is that is that it?
Jake (06:34):
Ah, that's it. Enums. Yes.
Enums. Exactly that.
Yep. Yep. Yep. Yep. Yep.
Yep. I wanna write these downbecause otherwise, I'm going to
forget them.
Michael (06:44):
You will forget it.
That is what always happens.
Jake (06:47):
Yep. So I said first, I
said we should talk about
tenant, storage. Mhmm. Talk toyou later about my policy,
segmenting by username of I'muser, and then you were talking
about enums. And what else wasthere?
(07:12):
Did I say something else or no?
Michael (07:16):
Batch testing.
Jake (07:18):
That's it. Batch testing.
Thank you. Batch testing. We'll
see if we get through all that.
If we don't, that's okay. Wecould talk about it some other
time. We're on episode 160, soI'm gonna write that down here
too. And this is why Caleb justtalks about stuff as soon as it
comes to his brain in notes onwork, which I gotta say also, if
you have not listened to that,you definitely should because
(07:39):
it's really awesome.
Michael (07:43):
Sorry. Tell me about
tenanted storage.
Jake (07:47):
Tenanted storage. Okay. So
here's the challenge. Right? I
and maybe it's unnecessary, butmy fear is that if I'm using
something like Spasie MediaLibrary, and I have models that
are scoped to a tenant.
It feels weird to me to just usethe media library to just add on
(08:08):
a media item to that tenant, andthen it just stores it in this s
3 media location. That's it. Youhave the media disc, and
everything's just chucked intothe root directory. And I guess
I just feel like I want a littlebit more separation between the
files than that, than a recordin the database. Like, I want to
protect myself somehow from myown stupidity, and you know what
(08:32):
I mean?
Accidentally giving someone elseaccess to something that doesn't
belong to them or them beingable to be nefarious and get to
a URL that they should not beable to get to or to generate a
a, you know, temporary link to afile that they should otherwise
not have access to. Yeah. Andthat's so that's that's my fear,
and maybe that's unfounded, butI don't think it is. I think
(08:52):
it's actually probably a goodidea to protect myself from
those sorts of things where,like, I might accidentally
forget or have something likethat. So it's just this layered
approach, this idea of layeredsort of, you know, things that
prevent me from havingunauthorized access to these
different file locations.
Michael (09:11):
Yeah.
Jake (09:11):
So what are your thoughts
on that first before I dig into
it? Like, yay, nay. Do you thinkthat seems like a reasonable
fear? Is that what do you think?
Michael (09:19):
I think I I think the
main thing there would be, like,
collisions and file namesbetween tenants. But if you're
just using Laravel's defaultstuff where it where it
generates a file name from ahash or, you know, random string
or whatever it is that it does,then I think that's not a
concern. I think the default isto, like, store those things as
private files. So you can'tlike, you can't get a directory
(09:41):
listing on s 3, and you can'tjust access these things without
a signed URL. So I think That'strue.
I think the opportunity toaccidentally stumble upon a file
is taken care of at this, youknow, at this high level by S3.
I think if you are accidentallyleaking media records between
(10:04):
tenants, The problem is in,like, application application
logic land where you are leaklike, if you are leaking media
models between tenants, you areprobably potentially leaking
other information betweentenants. And that's something
that you need to to look at.That said, segmenting Which
Jake (10:24):
I agree. I that and that's
what I'm saying is, like, I I am
confident that we will get itright most of the time, but I'm
afraid that there will be timesor there will be something where
I will you know, somebody ifit's even if it's not me,
somebody on my team willaccidentally write something or
we want to realize that it isleaking something.
Michael (10:41):
Mhmm.
Jake (10:41):
And in the case that it
does, I want to have another
mechanism that will protect mefrom giving that person access.
Michael (10:49):
Mhmm. Yeah. So, I mean,
if you if you link the model to
to the wrong user in the wrongtenant, you're going to link
access to that file anyway.Because I assume, given that you
are using signed URLs to accessthose files, if you happen to
(11:10):
return that model, you arereturning a authorized link to
that file anyway, irrespectiveof where it's stored.
Jake (11:17):
And this is the backstop.
Right? So the backstop is if I'm
storing them so let me just tellyou sort of this leads into my
second part here, which is, thisidea of a policy in AWS that
allows me to control access toparticular folders. I guess you
(11:40):
could call it clip particulardirectories inside of a bucket
based on the user that iscurrently authenticating to that
bucket. Okay?
So the way that I have this,this policy set up is it says
allow listing of buckets forwe'll just let's just call it
Jake's media bucket. K? So youcan list buckets for for Jake's
(12:04):
media bucket because you have tohave that permission for some
reason in order to be able to doanything in there. You have to
have the ability to listbuckets. Great.
Yep. But the ability to get,put, or delete is restricted to
a path that is scoped to theusername of the I'm user that is
(12:27):
currently having this policyapplied to them. So if I have a
user, an I'm user called, let'sjust use Wilbur. Like, Wilbur is
the name of my employer. That'sthe tenant is Wilbur.
Then what happens is Wilbur hasaccess to Jake's media bucket
slash Wilbur slash star.Anything within that directory
(12:50):
works. It it'll just work. I Ican get I can get put and delete
in there, which is great. So ifthere's another one, what's the
name of your employer?
Michael (13:00):
LMG.
Jake (13:01):
LMG. So if we also have
jakesmudiebucket/lmg, even in
the case that I accidentally getaccess to a record that belongs
to LMG, If I try and go getsomething that lives in the LMG
bucket, because I'mauthenticated as the Wilbur
tenant, as far as thecredentials to AWS are
(13:21):
concerned, I will not be able toget assigned URL to LMG.
Michael (13:25):
Okay.
Jake (13:26):
So that is the backstop.
It's like, yes, I may have a me.
I may have access to the modelsomehow, but the signed URL,
when I go to get that will becovered up, will be protected by
the fact that I have differentAWS credentials based on the
tenant. Now that that brings inother challenges. Right?
There are other challenges,like, now where do you store
those AWS credentials and thosesorts of things. But in theory,
(13:50):
without thinking about thoseother things, that is my
question. It's like, is that agood idea? Does that sound
reasonable? And I think it does,but I'd I'd like to hear what
your thoughts are.
Michael (13:59):
Yeah. So we we're at
the moment are using the tenancy
for Laravel package that kind ofhandles the stuff on the fly. So
based on whatever your tenantis, it will swap out the storage
at as it's part of theapplication boot process. So it
goes and scaffolds it and sets aprefix to, like, whatever the
(14:20):
tenant ID is. So everything's inone bucket, and then it's slash
tenant whatever the UID is orwhatever the ID
Jake (14:26):
is. Okay. Yeah. Sure.
Michael (14:27):
So all of that stuff is
segmented, and we use, domain
based tenancy. So, you know, itwould be
wilber.whateverlmg.whatever. Andso it would then switch to that
tenant. You would authenticateto that tenant. And then but but
it's still all using the sameset of credentials to access
each of those tenants.
(14:48):
So even though the flowersthemselves are segmented, you
still have so I think you withyour IAM policy, you have an
additional layer on top, so longas you're also swip switching
the credentials as part of
Jake (15:00):
that Yeah.
Michael (15:01):
Boot process there,
which I think Yeah. I think that
adds a little bit of extraprotection. I think the the way
that the the tenancy for Laravelpackage does it, it's just
swapping the bucket. And thatand that, I think, is more
around a portabilityperspective, where if you wanted
to pick up a tenant and shovethem onto their own EC2, for
example, onto their own node,you can do that and just pick up
(15:24):
that whole thing and bring alltheir storage and then put it
somewhere else as opposed to,like, isolating between the
buckets. So I think you've gotthe extra layer at the moment
where, you know, you are you'reaccounting for the possibility
of inadvertently leaking themodels.
But because you are alsoswitching the credentials used
(15:44):
to access those files, Even ifyou did get a URL, it would
still deny your access anywaybecause it'd be generating
Correct. A link to a file thatlike, with with a different sign
in key. So
Jake (15:59):
That's right. Yeah. That's
that's the idea.
Michael (16:01):
Yeah. I think I think
that's probably fine. And, like,
it obviously depends on whatyou're trying to protect here.
Like, if it's just profilephotos, then it's probably not
as critical. But I assume, giventhe nature of the business, that
you are protecting financialinformation, things like that,
where you would yeah.
(16:22):
You would wanna be, you know,protecting that stuff at a
higher level. So yeah.
Jake (16:27):
Personally identifiable
information is the biggest, you
know,
Michael (16:29):
the biggest thing.
Jake (16:30):
You don't wanna leak that
one. Yep. Yeah. And so and I'm
also quite sure that, you know,the the level of clientele that
we're gonna be servicing,they're going to want to know
that in addition to logicalseparation of those files,
there's also going to be, youknow, some sort of separation of
credentials as well for thisexact reason, for the reason
(16:51):
we're talking about. Now thething is I haven't exactly
figured out how I'm gonna dothis yet is the only trick.
Like, I don't know the actualarchitecture I'm gonna use to
accomplish this. So one way I'vethought about doing it is the
and the interesting thing aboutthis tenant app that we have is,
like, the max number of tenantswe'll ever have is, like, 15.
(17:12):
Right? Like, it's it's not Yeah.Like, each each tenant can get
set up manually.
Like Mhmm. I could store eachone of the credentials in the
ENV if I wanted to. You knowwhat I'm saying? Like, could
swap them out but based on thetenant just on using, like, some
convention of the naming of theENV and be done with it. So
(17:35):
it's, like, what I could do is Icould use a different I could
even set up in the file systemsdot PHP a different disk per
tenant.
The the tenant could have theirown disk, and then I would use
the credentials. I could storethe credentials in there, and
then I'd swap out the disk andthen be be good to go. So so
that's that's an option as well.And that would probably happen
(17:56):
during the the service provider,you know, just booting up the
app, then you'd swap out thedisk, and then you do all that
stuff. Yeah.
Michael (18:02):
I think I think that's
probably an easy way to do it.
If you were to configure a diskrather than dynamically
switching the credentials of arather than trying to swap the
(18:26):
credentials used for a singledisk at runtime.
Jake (18:30):
Right. Right. Yes.
Exactly. And then the hope there
would be, the hope there wouldbe that, you know, you wouldn't
make the stupid mistake ofsaying, like, okay.
Well, when you're trying to goget the the documents for this
claim, just use the team ID ofthat claim and then swap to that
disk. It's like, no. No. No. Theonly time you ever swap the disk
is at this time you boot theapp, and that's based on the
(18:51):
currently logged in tenant.
That's it. And no other placesdo you ever do that. You always
reference the disc that's loadedinto the existing, you know, the
tenant, the users that's loggedin. Never do it based on the
actual claim itself. Yeah.
So, yeah, I think that that'd bethe only way. So but I I think I
would sleep better at nightbeing knowing that that was the
case. Yeah. That there's no wayfor them to swap that out, or if
(19:13):
I did leak a claim, it's notgonna, like you know, it would
just basically be like theclaim's not there. It doesn't I
I don't see any folder by thatname.
So Yeah.
Michael (19:21):
Yep. I think that's
Okay. Cool. I think that's
reasonable.
Jake (19:23):
Okay. Cool. That that's
helpful. I appreciate having
that discussion. So, again, I,with that sort of, like, I'm
policy thing, just as a headsup, like, I I can throw that in
the gist log if that's helpfulfor anybody.
The really big benefit to me wasthat I didn't have to write a
new JSON policy every time Iwanted to make a new user that
had access to a specificlocation inside that bucket. All
(19:46):
I had to do was create a newuser, attach that policy, and I
was done. Attach one policy. Andso all you have to do there is
basically, reference theusername and the path by just
using I think it's actually adollar sign. I think it's a
dollar username, inside of thepolicy itself, and it will use
the username of the, of thelogged in user.
(20:07):
Now one other thing to noticethere is as well, it's case
sensitive. So, like, if you haveWilbur upper case, the capital
w, or Wilbur lower case, thoseare 2 different locations, or 2
diff yeah. Yeah. The name of theuser is case sensitive, and so
it matters, when you're tryingto look at that disk location.
So, yeah, there you have it.
(20:28):
There you have it. Okay. Nice.
Michael (20:31):
Yeah. I think I think
you're covering your bases there
given what you're storing. Ithink the the only decision
really you need to make is doyou wanna configure, right, n
number of disks, or do you wannafigure out how to dynamically
switch them at runtime?
Jake (20:44):
I think I think having a
number of disks is probably
fine. The only the only thingthat I will have to be careful
about or just consider is thatwhen I'm doing, like, the media
stuff, Spassie media library, Ithink there's a way though. You
could just say on disk. You justput it on a specific disk, like
it's a fluent it's a fluentcall. Yeah.
I can just do that. No problem.That should be easy enough.
Michael (21:05):
And I don't know where
I saw this recently. I think it
might be, like, Stephen Baumannhas been tweeting these kind of
things recently where he's tookand and maybe it was you that
retweeted it, talking aboutputting queue names into an
enab. And I think you could dothe same thing with with your
tenant, like, with your filesystem disks. Just and that way
(21:26):
you can
Jake (21:27):
run out of
Michael (21:28):
and things like that.
Yeah.
Jake (21:29):
Yeah. We do we do that
right now with any of our disks
as we put them in. Now okay.This is actually an interesting
one too. Let me so let me let mecover what you're talking about
first, which is yes.
In file systems dot PHP, insteadof having a string name for the
disk, we use a enum there. Nowwe were using just classes and
constants. Right? Because withthe class and the constant, it
(21:50):
always references the stringvalue. There is you don't have
to do arrow value, which looksso much nicer.
You could just say disk doublecolon wilber or disc double
colon LMG or whatever you saidyou said yours was. Yep. Whereas
now I have to do disc doublecolon Wilbur Arrow value, which,
ugh, I do not like that. That'sthat sort of sucks, but you have
to have the stringrepresentation of it. You can't
(22:11):
do anything else.
So, wish there was a better wayto do that, but there isn't. So,
yes,
Michael (22:15):
they're using
Jake (22:16):
enums in that way.
Michael (22:18):
Samuel, who who wrote
tenancy for Laravel, also has
this package, for enumaugmentations, I guess you wanna
call them. And one of thefeatures of this package, one of
the traits that it includes isthe ability to make enums
invocable. So you can you cando, you know, file system disc
(22:39):
colon colon wilba and thencaller as a static function, and
it will return the string value.So that way, you get, you know,
the ID support, you get thecompletion, and you also get,
you know, the ability to to getthe value of that in a member
without having to then chain onour value. So that that makes
sense.
Jake (22:59):
Pretty good.
Michael (23:00):
But, yeah, it is it is
kind of annoying that PHP does
not,
Jake (23:05):
and for you automatically.
Yeah.
Michael (23:06):
Casting it to a string
in in a, you know, in an array
context like that.
Jake (23:12):
Yeah. Yeah. Yeah. It's
annoying, but whatever. So we've
we've just swallowed hard andjust been like, okay.
We're just gonna make it. We'rejust gonna do it that way. Arrow
value it is. And so whatever. Wedeal with it.
But speaking of enums, tell meabout your enums, thoughts here.
Like, you Enums. You were good.Yeah, your Enum adventures. So
you said something about maybe,like, making a little video
(23:36):
course or something?
Or what what are you talkingabout?
Michael (23:38):
Like a little mini
thing. I don't I don't know
exactly what it looks like, butthe the kids had a sleepover at
the grandparents' place on theweekend. So I had a little bit
of time, which I spent, ofcourse, most of that time
getting my setup working for forrecording video. But I just I
just put together, like, alittle 2, 3 minute off the cuff
(23:58):
video talking about, you know,in terms. And we we we all have
them now in PHP since version8.1, and we'd love to use them,
and we love talking about them.
And I think there's someinteresting opportunities to to
explore, like, usage of thembeyond just, like, here is a
thing that has like, it's eithera fact enum that returns a
string value or or it's just, abasic enumeration that just has
(24:23):
case names. But there's there'sa lot of different ways of using
it. Like, PHP doesn't provide anice way to return a list of
options or, like, it gives youcases, but it doesn't allow you
to target the values or the keysand things like that. So there's
ways around that.
Jake (24:39):
You gotta kinda build them
all in with your own traits and
all that nonsense.
Michael (24:42):
So, yeah. There's
there's no. Just just to kind of
talk a little bit through thatand and what that looks like,
some options, you know, thisthis enum package that I
mentioned is a good way to kindof bring that in in a way that
you can use it across projectsand across enums really easily
without having to, you know,manage your own traits and
things like that. But then alsotalking about more interesting
(25:04):
use cases like, providingstateful functionality, to use,
like, your invoice status.Example from your
Jake (25:17):
Ah, yeah. My
Michael (25:18):
Laracon talked last
year. You know, if if you have a
a status of, you know, draftand, active and paid and debt,
for example. Like, you canattach descriptions to those and
use them to label things in thein the UI of your application
based on
Jake (25:36):
Sure. Yeah.
Michael (25:37):
The current state of
that enum. So, you know, talking
a little bit about that, talkinga little bit about, you know,
factory instantiation of enumsand things like that. So there's
there's some, like it's not it'snot like a huge service area,
which I thought it would be agood idea to do it because it's,
like, fairly limited in scope,and you can kind of go, this is
(25:58):
everything in quotes that thatyou can do and it's just done.
But I think there's interestingexploration that, you know, you
see bits and pieces every nowand then, but not, a great deal
of discussion around that kindof stuff. So I thought, you
know, just as a little bit offun.
Of course, since since that 3minute video, I've had
absolutely zero time to work onit.
Jake (26:19):
Right. Right. I because
when the
Michael (26:21):
kids are home, there's
there's no time, and I can't
when the kids are asleep,because one of them sleeps, you
know, obviously, that wall aswe've discussed before, so I
can't be in here recordingvideos at night. So
Jake (26:30):
Yeah. Yeah. That's I I get
it, dude. I'm I'm there with
you. Like, I have to, I've been,I mean, it feels like we're in
an eternal house project mode.
You know what I mean? Like, itjust never ends. So I'm putting
up casing and baseboards rightnow. But, yeah, I can't do it if
the kids are in bed because Idon't wanna wake the kids up. So
it's like, you know, you onlyhave so much time.
(26:50):
So today, all the kids were at asoccer game. So I came home from
work and just got got to goingon it because it was like, I'm
not gonna bother anybody if I'mmaking lots of noise. And so
Yeah. Tore it up, but that's howit is. Yeah.
No. I think that's I'm curioushow many people in the PHP
ecosystem are not using enums. Imean, I guess the prerequisite
(27:10):
is you have to be on PHP 8.
Michael (27:13):
8.1. Yeah.
Jake (27:14):
8.1? And, so, I mean, you
know, depending on what
percentage of people are on 8dot 1 or above, that's gonna be,
you know, that. But then of thepeople who are on 8 dot 1 and
above, who's not using enums?You know, I don't know. It's
like one of those features.
It's one of the I I think yousaid it the other day. You're
like, man, it's one of myfavorite features of PHP now. We
(27:35):
use it we use it everywhere, youknow. And any place that I see a
magic string, I'm like, nope.Nope.
Nope. Nope. Nope. Nope. Don't dothat.
Please don't do that. Please usethe enum.
Michael (27:42):
We have we have this
enam called yes, no.
Jake (27:46):
Oh, I like that.
Michael (27:47):
It has 2 members. Yes
and no. But we because for
historical reasons, a lot of ourdatabase actually stores yes and
no in fields as opposed to
Jake (27:57):
Instead of 1 or 0s? Yeah.
Michael (28:00):
So in order for us to,
like, operate in a sane way in
our code with booleans and thenconvert them, we've got, like,
this factory method on the yesno enum called yes no from
boolean value. And that way wecan handle situations like you
pass in, like, some Boolean andthen, like, if it's true, we
return yes, and if it's false,we return no. Like, just that
(28:22):
Genius.
Jake (28:22):
I mean
Michael (28:22):
those small little
things. But you correlate all
that behavior in one place,which means you can test that.
Like, you can throw differentthings at it. You can decide
whether or not you want tohandle null. Like, is null an
invalid state?
Does null return null from thisenum? Or does null default to
false? You know, all those kindsof different things that you
that you co locate and thatbehavior is there. So you can do
(28:45):
it anywhere that you need to,you know, anywhere we need to do
that transformation from aboolean to a string of yes or
no, we can do it all in thatenums. Sorry.
Jake (28:54):
And vice versa. Right?
Because if from the database,
you can cast to an enum. So youcast from the enum to the yes,
no type or sorry. Well, yeah.
You cast from the database tothe yes, no enum, and then you
have all that behavior again.So, like, when you're
referencing that value, thatcolumn, just, you know, you're
dealing with the enum. So that'ssuper handy, man. I mean, all
that behavior you get and thenplus just the confidence to know
(29:15):
that I'm dealing with one ofthese values. You know?
Michael (29:18):
And you know just You
know, when when you're doing a
match inside like, in thecontext of an enum, you you
never have to put a defaultstate in there really because
you can only have an enam thatexists in a valid, representable
state. So yeah. And then thisis, like, here's the
documentation talks about thisin the in the notion of, like,
(29:39):
the enam exists to to preventyou from having a value that is
in an unrepresentable state orsomething like that. Like, if
the enum is instantiated, thenthe enum is it contains a valid
state. It can't be anythingother than what is defined in
the enum.
You can't have an enum with avalue of null.
Jake (30:01):
So Yeah. Yeah. The only
case in which you'd have to have
a default state, and I've runinto this a couple times, is so
somebody will have a methodcalled get options or get labels
or get colors.
Michael (30:12):
Mhmm.
Jake (30:12):
Right? And so what they do
is they start listing all the
enum cases in the left and thenlisting all the values that they
should be associated to on theright hand side, which is great,
except for when you add a newcase and you forget to add it
into that method. Mhmm. And nowyou have a default state because
you can have a valid enum valuethat does not have a state. And
so instead, what we've tried todo is do something like and and
(30:34):
so this is a case for at,attributes, PHP attributes.
And so what I will do is I willinstead of having and this gets
a little bit messy. It's not theit's not the right solution for
everybody. But instead of havinga get labels, and I'm sorry, I
will still have to get labels,but what I will do is on the
(30:57):
case itself, I will put anattribute of label on it, and I
will define the label rightabove that case. So if I'm
adding a new case, all I have todo is follow the convention and
add that new label on that newcase, and now my get labels
says, give me all the cases andloop over all of them and give
me the associated label. And ifthere's ever one that doesn't
(31:18):
have a label, it throws an
Michael (31:20):
error. Mhmm.
Jake (31:20):
And so I do the same thing
for colors. I do the same thing
for whatever. So it's like allof that stuff is right there
located on the case itself. Nowlike I said, does get a little
bit messy sometimes if you havetoo many things you're trying to
do, but it actually works prettydang well, I gotta say. So
that's another thing you couldadd to your enum talk is using
attributes to co locate thatstuff right up next to the case
(31:42):
rather than in a match function.
Michael (31:44):
Yeah. I like it.
Jake (31:47):
I could send you an
example of that too. Yeah.
Michael (31:49):
I I
Jake (31:50):
because it is a little bit
tricky with the reflection. You
know what I mean? You have touse that you know, you have to
use the attribute and then thereflection stuff to get the
option, or they get the label
Michael (31:56):
or whatever. That is
that is like I actually looked
into like how to put your ownattributes together. And because
it is all meta programming, theonly way to reference the
attributes is to use thereflection API to do things to
look for specific members of ofa class. And then you've got to
look to see it, like, is therean attribute attached and all
this other stuff? I guess it'snice if you do it in such a way
(32:20):
that it's reusable, and you canjust put it anywhere.
But it's also like That's
Jake (32:23):
what it is. Yeah. Yeah.
That's what it is. And so, like,
if you know, what I do is I havean attribute call or a trait
called has labels.
And then has labels has thatmethod on it, and then I already
know the attribute is gonna belabel, and then it just you
know, I don't I only have towrite it once. And now I know I
have a labels function on therethat automatically uses
reflection and the labelattribute to get the labels. So
it's not difficult to implement,and, you know, the the trait
(32:45):
says exactly what's on the youknow, does exactly what's
printed on the tin as you guyssay. Yeah. I'll send you that,
and I'll send everybody elsewho's interested in that too.
There actually was a LaravelNews article that I used to sort
of get me on this path. Althoughthe Laravel News article was,
like, adding your own attributesto your enums or something. That
was a while back. Yeah.
Michael (33:07):
Nice. Yep. That's good.
Go go give credit to
Jake (33:09):
the author.
Michael (33:09):
Definitely definitely
do that. Yeah. We'll reference
that as well. That'sinteresting. Very good.
Jake (33:18):
Awesome. Okay. One other
thing. What do we got here? We
got we got the testing of,batches.
Michael (33:25):
Yeah. So you, you were
doing this look, kinda grim. And
I think the realization that wecame to in that chat was that,
yes, it is grim, but there's notreally a better way of doing it.
Jake (33:37):
The only yeah. No. There
is no better way of doing it
currently. So let me explain thesituation. So I've got a action
that is dispatching a batch.
So the action creates a claim,and then I have a batch that
gets dispatched that or is thatright? Yeah. I have a batch that
(33:59):
has 2 jobs added to it, justlike add notes cover page and
add claim cover page. Those arethe 2 jobs, and then I dispatch
it. And then I have a then,which tells the batch when you
are completed successfully, dothis action.
Right? And then you have acatch, which says if anything
fails, you should do this.Right? So that's the situation.
(34:20):
Bus, jobs, here's the jobs,dispatch, then catch.
Right? Those are those are yoursort of methods you have there.
So, you know, what I wanna do isI want to assert in my test that
there were 2 jobs dispatched,and that the 2 jobs that were
(34:40):
dispatched were these 2 jobs.Now some people would call that,
like, spell check testing, and Iwould agree. It is spell check
testing.
But what I'm trying to do is I'mtrying to prevent future
developer, not me or me, fromaccidentally commenting one of
those out or having somethingstupid happen. You know, some
merge conflict comes in and theyjust delete it, and now my test
(35:01):
is, you know, if I don't havethis sort of spell check test in
place, it's like, yep.Everything's fine. So I I that's
what I'm trying to avoid. Right?
Yeah. I'm not testing the actualjob, the the the add claim cover
page or add notes cover page.I'm not testing the job. I'm
testing that job separately, butI want to know that the batch is
getting those specific jobs.Okay.
So Mhmm. The the way that youcan do it right now is in your
(35:22):
test, you batch fake, and thenyou batch a certain dispatched,
and then within there, you get apending batch. So that pending
batch contains the jobs that areadded to the batch. So you see
pending pending job arrow jobs,that will give you that. And so
then you can do assertionsagainst that.
(35:43):
That just gives you a collectionof them. Right? It just gives
you a collection of jobs. And soin order to assert, you could
say count count that there's 2,and that works fine. Yeah.
You can count there's 2. Butthen if you wanna assert that
the 2 jobs that you areexpecting to be there are there,
you kinda have to, like, map tothe get class of the job. You
know, you kind of map over eachof them, you know, return the
class name of the job and thencheck to see if it contains the
(36:07):
2 jobs that you're expecting.That's that's sort of crappy. It
doesn't feel good at all.
It feels like it should besomething like pending batch
arrow has job, my job. Pendingbatch has, you know, has arrow
has job, my job. And then itshould I I would want to do
something like pending batch,then, you know, whatever. Did my
then work? You know, I Ishouldn't even actually have to
(36:29):
do then.
I if I wanted to call then, Icould just do it. So
Michael (36:32):
Yeah. I feel Anyway. I
feel like, number 1, I like
these kind of smoke tests forevents, for jobs, for for things
like that, where you just wannafake that this happened. Right?
You don't Yeah.
You don't care the side effectsof those jobs running or those
events firing or whatever else.You just wanna make sure that
(36:52):
given you hit some controller orsomething happens in your
application, this expectedbehavior was fired. Like, these
jobs were dispatched. And then,as you say, testing the actual
behavior of 1 or more of thoseindividual jobs is, you know, is
the concern of instantiatingthat job,
Jake (37:11):
calling it a test
somewhere else.
Michael (37:13):
Yeah. Like, a test
somewhere else that does that.
So, I feel like JMac has talkedabout this before, about, like,
testing batch jobs or somethinglike that. Maybe he's worked on
it. Like, I'm I'm sure I'veheard about it in passing
somewhere.
And I feel like it was J Mac,but I could be wrong that it was
him, around, you know, a betterway of doing this stuff.
Jake (37:38):
Yeah. So I mean, the what
I what I ended up seeing and
maybe throwing out as asuggestion, and if anybody feels
inclined to do so, you shoulddefinitely do this. I think it's
a great pull request, honestly,to the framework. We have this
idea of a certable JSON insideof our JSON tests, which is
awesome. It's really cool.
(37:59):
So you can say assert JSON, andthen you have a closure, which
has an assertable JSON. And sowhat that allows you to do is
allows you to make all sorts ofassertions against the JSON
that's in there. You get thisreally nice class that has all
these little helper methods togive you the ability to test all
sorts of things in your JSON,the payload that's coming back.
Super cool. So my suggestionwould be here, when you say bus
(38:21):
assert dispatched, instead ofjust getting the pending batch,
what you would get is somethinglike an assertable pending
batch, and then it would thatthat assertable pending batch
would have little helpers on itthat would allow you to do
exactly what we talked about.
Is this job in the list of jobsthat's getting dispatched? You
know, does my Venn, closure,when it's executed, have the
(38:44):
existing have the side effects Iwould expect? That sort of
stuff. And so this was an examthat that was some, a suggestion
that somebody gave on Laravel,sorry, on Laracasts, forums was
they were like, well, when I domy when I do my assert batched,
I take that pending batch and Iknew up a fake batch that I have
passing in the pending batch,and then they just do exactly
(39:05):
what I talked about. They havethey've created all their little
helper methods to do exactlythat, test to see if the job is
in there, etcetera.
So it's actually not thatdifficult of a PR to make to the
framework, but it would be apretty cool PR to make. So if
anyone wants to scoop me on thatone, go for it because I'm
probably not gonna do it. But Ithink it's I think it could be
really cool. And, yeah, DavidHemphill said he talked to
(39:28):
Taylor about it. And Taylor waslike, yeah.
There's no better way to do itright now. And so not saying
that there's not a better way itcould be done, just that
currently in the framework,there is no better way to do it.
So if you're looking for yourfirst pull request to the
framework, go for it.
Michael (39:41):
Pretty good one.
Jake (39:42):
It would be a good one.
Michael (39:44):
Excellent. I don't I
don't think I've got anything
else.
Jake (39:49):
Okay. I I think this is a
pretty valuable episode. I know
we talked about some really goodstuff in here. Yes.
Michael (39:55):
Good stuff. Thanks.
Thanks for the, the hot tips
around the because that givesthat gives me some ideas around
progression from, like, this iswhat we used to do, pre PHP 8
point 1 and enums. This is howyou might do it using, like,
just an inline method. And thenthe attribute itself is nice
(40:15):
because it gives you the abilityto kind of do that in a
consistent way across all ofyour, different emails without
having to, like, know, implementthe same match thing everywhere.
It's just it's just gonna beavailable. Correct.
Jake (40:31):
Yeah. And it protects you
against it protects you against
that stupid thing that I talkedabout, which is, like, somebody
adds a case and forgets to addit to the method, which has
happened to me before. That'sthe reason I know it's a danger
is because it actually hashappened. And so what you end up
having to do is have thisdefault method that just throws
an exception in the case thatit's something other, and that's
annoying too. That doesn't feelgood either.
Yeah. And so the like I said,I'll send you a code snippet of
(40:53):
what I have and what, you know,the nice thing about it, that
redeeming quality is if there isever a case that does not have a
label on it, it throws thatexception saying, well, you have
a case that doesn't have alabel. So you can't have a get
labels attribute or whatever. SoYeah.
Michael (41:06):
It's always funny
testing, like, that kind of
inbound behavior because youfind yourself Yeah. You know,
duplicating all of that stuffjust to make sure that, like,
yeah, I have set. And then,okay, I ran the test and it
failed because I forgot to doit. So you can go back and and
do it. But it's just like, nowI've got a copy and paste the
description from the enam intothe test, and then, you know, if
(41:27):
one changes, the other one hasto change, and that kind of, you
know, leads you down the path offlaky testing.
So yeah. I like I like thisidea.
Jake (41:38):
I will send it to you my
friend. And maybe I'll throw it
in a gist, and I will send it tothe wider world as well for
anybody who cares to do so. AndI will find that Laravel News
article as well and send that toyou.
Michael (41:48):
Yeah. I found I found
that Laravel News article.
Jake (41:50):
Sweet. Yeah. That's a good
one. I mean, that's literally I
mean, I don't need to share minethen. I mean, that's exactly
what I did.
What he has there is exactlywhat
Michael (41:57):
it is. From,
Jake (41:58):
Rob Fonseca. Yep. Yep. So
grab credit to Rob. Thanks, Rob.
Michael (42:03):
It's good.
Jake (42:03):
Good good call.
Michael (42:06):
Cool. Alright, dude.
The only other thing I have to
say is we crossed into we onlyhave 47, I think, early bird
tickets left to Laracon for thisyear. So I think we're about 8
minutes away. So we are we aredoing well.
We're having lots of stuff.We're getting into the, like,
(42:26):
final stages of, you know, myside of the things now. You
know, making sure that thespeakers are all set, starting
to finalize all of our Oive allthe Taylor is setting us up the
bomb over here with, just thethe level of of production for
Aragon US this year. So we'vegot some ideas. We've got some
(42:47):
things that we're gonna do.
But we're looking forward
Jake (42:51):
to it.
Michael (42:51):
We just started
storyboarding our, I say we.
Nucleus started storyboardingand scripting the intro video
for this year. So, you know, wedid it last year, and obviously,
we have to follow-up this year.But we've got some cool ideas
for that as well that that we'llpursue, and some other fun fun
(43:12):
stuff. So I'm looking forward toit.
It'll be here before we know.
Jake (43:16):
You having to put a lot of
work into, like, your intro talk
or anything like that? Oh, boy.I'm talking about it.
Michael (43:23):
I may have made a
terrible mistake. Like, last
year,
Jake (43:27):
because it doing that last
year. Yeah.
Michael (43:28):
Well, because last
year, there had been a 4 year
gap since the last time we didour Sure.
Jake (43:32):
No. That
Michael (43:33):
makes sense. That makes
sense. You know, it was a good
idea to kind of set the tone andand set the same for, you know,
why we do what we do.
Jake (43:40):
Yeah.
Michael (43:41):
I just don't know.
Like, I have
Jake (43:45):
How do you do that every
year? It's hard to do every
year. Yeah. Yeah. Yeah.
Michael (43:48):
I don't think you need
to do it every year.
Jake (43:49):
No. I don't think
Michael (43:50):
so either. I will I've
got some things written down,
like, I've got a document, and,like, I will do some kind of
opening address, but I don'tthink I'm gonna tell a story
like I did last year.
Jake (43:59):
I mean, honestly, I again,
let's go back to the Aaron
Francis whatever blah blah blah.Sorry, Aaron. We should be
giving you royalties orsomething. But, to intro Laravel
or Laracon this year, heliterally just I mean, it was
honestly like a tiny littlestand up routine that took,
like, 2 minutes. Right?
It was it was funny. It was itwas very chill, like but, you
know, the thing is too is it'slike you don't wanna put a ton
of time into it either because Imean, let me see. How do I
(44:22):
preface that? You want us to begood, but, like, also half the
people in the room are justgetting seated, like, when you
kick it actually kick it off.It's just like, you don't wanna,
like, stake all this time on itand then be, like, be really
frustrated if half the peopleweren't listening because they
were just stopping their chatthey were having with somebody
they haven't seen in a year.
So anyway
Michael (44:40):
Yeah. I think I think
this year is gonna be much more
high level. Just, like, youknow, the the general, like, how
many how many of you here foryour first time, you know, how
many here for your 4th time?
Jake (44:50):
Oh, totally.
Michael (44:51):
Yeah. Just like that
kind of stuff, you know, and and
just set the tone, you know, setthe rules and and things like
that around expectations, andthen, yeah, just launch straight
into it this year, I think.
Jake (45:01):
And what we all realized
this year at Lyricon US is
people are really just there tosee the people anyway. I mean,
like, the talks are great. Youknow what I mean? But, like, it
was so heavy emphasized, like,just there was, like, a whole
backroom that it was just, okay,people who wanna hang out and
just wanna watch it on a screen,just go back there and chat. And
a lot a lot of people did.
So it was cool. And so yeah.Same feel. Right? Don't put too
(45:21):
much pressure on yourself.
Like, the fact the the thingthat you're providing is the
space for people to meet. That'sthat's what you're providing,
and you're gonna do thatregardless. So you've already
won. You know? Yep.
So Alright, dude. Alright.Episode 166? 162. 162.
Find show notes for this episodeat northmeetsouth.audio/162. Hit
(45:44):
us up on the Twitters or the xatmichaeldorinda@jacobenorranorthsouthaudio.
Rate us up in your podpodcatcher of choice. 5 stars
would be amazing. And if you arelooking for custom keyboard
keys, you should check outdappkeys.com.
I have I sent another, I sentanother picture today. Let me
(46:06):
make sure it's DAP keys. It isDAP keys, I think. I think. I
think.
I think. I think. AnywayCampfire. This dude, Austin
Cameron what's that?
Michael (46:14):
The campfire? That was
sick.
Jake (46:16):
Yeah. Austin Cameron, is
this dude's name. Met him at
Laracon, but he gave me a littleLiveWire keycap and a little
Campfire keycap. Holy crap. Bothof them are so cool.
They're, like, an acrylic. Mhmm.They're awesome. I I can't wait
until he opens up his site stuffbecause I'm going to be buying
some of them. And and I toldhim, I was like, yeah.
(46:37):
I've got a low profile keyboard.And so he was like, oh, yeah.
Maybe we can make a differentmold for that one or blah blah
blah. So he's gonna I think he'sgonna try and do maybe, like,
not a full size keycap, but nota low profile keycap either
because you can't really get toomuch stuff into the acrylic if
you do a super low profile. Sohe's, like, gonna do, like, a
medium height, and I'm, like,super awesome.
So I couldn't be more excited.I'm so geeked out about these
(46:59):
key caps. They look so awesomeon my keyboard. I'll have to
share. Yeah.
They look so fun. So, anyway,shout out to Austin. Thanks,
dude. Alright, everybody. Untilnext time, 2 weeks.
We'll see you then. Peace.