That really collapses the special cases down

Streamed

scratch


topics
  progressive web apps https://lobste.rs/s/wxlsdn/building_robust_frontend_using
  phlex is neat https://www.phlex.fun/ https://beta.phlex.fun/
  storyboook https://storybook.js.org/tutorials/intro-to-storybook/react/en/get-started/
    the discount storybook for non-SPAs is: one template that loads partials and renders them in various states

git/command line diff I use: https://github.com/Wilfred/difftastic

Origin todo:
x selector, replacement
x Domain: validate .replacement
x show on Domain page
x edit form
x safety! test that user can't eval ruby in selector or replacement with "#{foo}" - only if you were at Ruby console
x domains#new:
x   /domains/new is confused with /domains/example.com
x   if you load /domains/new.org/edit -> edit form but posting to create action
x Origin many-to-many to users for better 'is_author' flag? Does Origin do anything at this point?
x Domains: create and ban form submits to wrong place
x Domains: 2 duplicate domains in prod
x Domain: edit selector/replacement, update Origin for all Stories
  new page: list stories by origin, link from list_detail; link up to domain page
  domain edit page: give fast feedback with js on every keypress
  Domain.origin: error out if URL is not to this Domain
  Domain model spec for origin with bare domain, domain with trailing slash
  Domain model spec for fixing a selector updating existing stories' origin_id
  feature test for create + ban domain
  feature test for new domain
  feature test for editing a domain selector + replacement

working through questions:

  Domain: when editing selector/replacement, fail validation if a Story url isn't matched
    3 corner cases: domain with no path, domain with / but no path, extra stuff after identifier
    selector                             replacement     input url              output identifier           good or bad?
    https://github.com(/[^/]+).*     github.com\1    github.com/foo/bar     github.com/foo              good
    https://github.com(/[^/]+).*     github.com\1    github.com/foo/bar     github.com/foo              good
    https://github.com(/[^/]+).*     github.com\1    github.com/            nil                         good?
    https://github.com(/[^/]+).*     github.com\1    github.com             nil                         good?
    easy mistakes to make:
    https://github.com/([^/]+)       github.com/\1   github.com/foo/bar     github.com/foo/bar          bad
    https://github.com/([^/]+).*     github.com/\1   github.com/            github.com/                 bad
    https://github.com/([^/]+).*     github.com/\1   github.com             nil                         bad

    lobste.rs/u/pushcx -> lobste.rs/~pushcx

    footguns aside: is it good that it's possible for a Domain selector to not match? is that invalid? for root domains, what's the identifier?
    maybe the fallback in that else wants to be: return identifier 'Domain.domain' if the selector doesn't match
  Q: should Domain.origin use the story url or the normlized url?
    pro:
      don't have to include https?:// in the selector
      don't have to handle trailing slash on domain with no path
    con:
      have to explain what this is? maybe? this is a power feature for a small number of technical users
    this is an open question

  domain edit page: give fast feedback with js on every keypress
    show 3 recent URLs and what their output identifiers would be with existing vs your edit
    highlight changed rows
    always show 2 rows with root domain, with and without trailing slash
    also show first 10 urls that are not matched

title: that really collapses the special cases down
    

Transcripts are generated with whisperx, so they mistranscribe basically every username and technical term. They're OK but not great, advice appreciated.

Recording



02:47frici Monday and Happy are strange words to put together
moving trucks fighting each other and fighting the garbage trucks for space in the alley which is lots of yelling and banging and honking and big trucks beeping plus one of the neighboring apartment buildings is doing construction and so it basically spent most of the morning sounding like a dentist drill which was not super pleasant because that kind of high-pitched screaming metal noise cut even through earbuds that's a little rough happier than hearing a dentist drill for hours hey fritchie yeah happy monday is intended as ironical i really i submitted this article so like i obviously i probably like it but i really liked this article on progressive web apps using progressive or making a nice front end with progressive enhancement There's a lot of really good stuff in the gov.uk technology service manual, just tons of stuff. And so I just, I picked out one thing to highlight, although a lot of this is really nice with really thoughtful, experienced advice on building web services and thinking through UX. one of the the hard problems that comes with government service is you have to meet your constituents where they are and so that's a lot of people using odd devices old devices with disabilities with little understanding of technology speaking multiple languages and finding and developing a lowest common denominator kind of solution and then actually making that nice is an incredible challenge that i haven't an american i haven't actually used the web services in the uk but i have read their manual and i really like where they're at there's a just this core philosophy of leaning hard into progressive enhancement is a big one and it comes to me even with simpler stuff like on the archive pages for this stream there's some javascript and it rather than having controls and form elements and such on the page, the JavaScript inserts them if they only work with JavaScript. So if you have JavaScript off or the JavaScript crashes, you don't see unresponsive UI. You just see less UI, which I think is much nicer. So I generally really like this philosophy. And it's in opposition to what the Rails philosophy is becoming now in 7.2, which really shocked me because rails was a big trendsetter in the idea of progressive enhancement back in the late 2000s mid to late they So this pull request never got merged. We had multiple pull requests for updating to Rails 7.2, and this submitter, cpgo, closed theirs in favor of the other one that they saw as more complete. But someone named Matthias Rich popped up to say, hey, be aware of this default config that limits you to modern browsers, which I really appreciate, Matthias. nogweii Hello, after a while!
Posting this, but the gist of it is, is rails seven two has added a feature where they say things like we're only going to allow browsers that natively support these things, but they're not actually doing feature testing. Like this kind of detailed list would imply it's the most. I'm trying to be kind. Oh, Hey, nice to see you again. Welcome back. It's the most. frici Oh yeah i remember vaguely discussing this last stream? or recently anyway
frici hey Nogweii
Shallow, let's just check your user agent or is it user agent or is it the JS version of user agent? Yeah, it's user agent. And it just kind of greps for the name of a few popular browsers. And yeah, we talked about progressive web enhancement, I think on the last stream or two or three ago, because I was still kind of digesting this. And then I made a toy application just locally because I wanted to play with Flex, which is an alternate templating system for Ruby. nogweii @Frici sup!
frici oh we did cause I mentioned how much I hate grepping for User agent... its so bad and so wrong on so many many levels
The docs could use a little bit of love. And I may contribute there if I have the free time. But generally, I really like Flex. frici I may not fully remember when things happen I just remember what I rant about LUL
nogweii "Best viewed with a 800x600 monitor" LUL
yeah yeah you hate grepping for user agents because you see it as bad and wrong on so many levels and i remember when the web was getting started in the late 90s how much of that nonsense there was of oh you're using netscape navigator and this site is best built in internet explorer and vice versa it's such a painful road and it's funny because i know dhh was online then and he's the one who drove for this very Keep coming back to the word shallow because it's the obvious bad way. Yeah, best viewed with an 800-600 monitor. You were there too then, Nagwe. dpk0 web safe colours
ymeynot45 Hey all.
was actually a bug in the first stream was i had this this window of stuff i was streaming and it was cut off because instead of the 1080p height i wrote 1280 because for so long i had a 720 by 1280 desktop and so that number just filled itself in instead of 10 50. ah hello again tpk yes web save colors those were a fun one and why me why not 45 hello welcome i'm griping about pushcx https://www.phlex.fun/
rails misfeature in happier news and happier news flex is really nice i'm getting a kick out of this if you haven't seen it and you write ruby web code it's one of those where it's pleasant because the end result is nice and there isn't hmm so i'm only like a couple of hours of playing with it in so let me let me caveat a little and not over generalize but i haven't yet gotten the kind of terrible metaprogramming errors that i immediately feared when i saw this sort of thing of oh we're gonna have a method for each and we're gonna have some amount of transformations happening like symbols to keys and hmm you know i've I was impressed by, I think it's Yeah. Joel Draper's other project, which I believe is still in progress and still in an, yeah, in a call it alpha or early beta state of a testing library. I really liked this kind of API and it was stripped down. So I looked at his other projects and I saw Flex, which has some adoption. This is really neat. This is the kind of, you know, this is, I played with Hamill a bunch years ago for people who remember Hamill or what was the other one? Was it called Simple? There were a couple of these alternate Ruby templating languages that were moderately popular around 2010, 11. They all had big performance improvements. This guy doesn't, the docs here don't have the kind of chart of look, we're so much faster than ERB. And I sort of appreciate they're not hanging their hat on performance that they're hanging it on. Let's make something that's a little more expressive and easier to maintain. And having committed several sins with ERB. I look at Flex and I go, oh, well, that's got a lot of stuff that I like quite a bit. And the ability to each component is a Ruby class. And then when they call other nested components, they just call each other. So as an example, A nav could be this that has this concept of an item function. And so you're just kind of mixing functions and mixing other classes in a very comfortable way. So I've only just toyed with it, but it's very nice. So that's what had me going on about front end stuff, is I want an excuse to play with the newer Rails front end stuff. As suspicious as I am of that allow browser feature, nogweii being ruby classes makes testing much easier
Some of the stuff that's in Action Cable, in Hotwire, in Turbo, around partial updates of pages looks quite nice and not like an SPA. Yeah, Nagwe, the testing story for this... So I haven't gotten into it because I'm just playing so far with... Where's the main docs for it? Is it docs. Now it's... I don't have it up in this browser. pushcx https://beta.phlex.fun/
The beta.flex.fun. So the main, let's grab that for the chat and the scratch file. nogweii LUL
Testing story, and I haven't, is that it needs a little more documentation, but the testing story of, yeah, it's some Ruby classes and you just pass data into their initialize is nice. Honestly, I think a big chunk of the testing improvement that you might get out of it, like I said, I said, well, the first thing I said about Flex is some of the docs are a little thin, but the, let me see an example here. The way it couples data from the constructor down to the individual template is, and I'm not finding a great, is it advanced? Yeah, that one's missing too. Here's an example. So you just call it as a function and you pass things in. And in the same way, when you make, nogweii https://www.phlex.fun/#nokogiri shows how to use MiniTest & Nokogiri
attributes you're doing that kind of like def initialize foo at foo equals foo the standard verbose ruby setup of instance variables and having components that are so it's the component takes over some of the responsibility that would be in a standard rails controller action all the the template oriented things rather than having a They also would take the role of a presenter if you're using that. Oh, thank you. You found the doc. I knew I saw some example. I realized like the least interesting thing I can show on screen is me hunting around for documentation. So I try and keep that to a minimum, but it means occasionally I move on and then somebody finds things. So thank you for finding the link.

14:45yeah so here's exactly that thing i was talking about of you have so this hello would be a component and you pass in the data you want to render so rather than coupling the component layer to the end template with instance variables which is what rails does out of the box you're very explicit about what you're passing in and i have worked professionally in django for years and i never stopped preferring the verbosity that i had in django where you have to list all of the data that you are passing down to the template, as opposed to any helper method that runs, or really any method that runs in the context of your Rails controller can set instance variables that carry down to your template. And then not only is it squishy on the controller side, it's squishy on the template side, because until fairly recently with the, what is it called, locals? Yeah, until Rails fairly recently added this locals line at the top of partials, the template wasn't required to declare anywhere what variables it was going to go dig around in. And so that lack of coupling from either side was really rough for long-term maintenance. And this is... This is kind of a beats nothing solution because you end up with, if you look at the syntax, it kind of gives away the game of, oh, this is all happening in a comment. This isn't actually Ruby code. So what's happening is ERB, or I think it's a Rails add-on to ERB, looks for this magic comment on the first line. And then I can't imagine it's so reckless that it just evals this. I think it parses this. with some copy of Ruby syntax. Yeah, I'm kind of making stuff up here. nogweii definitely not vanilla ERB
I have to admit, I don't know how it's implemented, but the fact that it's in a comment is super suspicious to me. So something slightly odd has to be happening there. And then you get these, no, it's definitely not vanilla ERB Nagwe. And it's implemented somewhere in Rails and it's It does okay at giving you exceptions when these local variables aren't set for the individual partial, but again, that's just partials, not overall page templates. So I appreciate that rails is improving the story there, but flex that gets to start from the ground up of, no, we're just going to lean on Ruby for you can declare these. If you want to make this optional, you know, put your colon at the end of it, or put your colon default value at the end of it. So. Having not tested it, I have not actually written these. But I just look at the code, and I'm like, oh, the testing story is nicer there. You can test them totally in isolation. And yeah, that's just nicer. I've been wanting for a little while to make a sort of component library for lobsters. If you've used, what is it called, Playbook? or not rails, playbook, playwright, playbook. pushcx https://github.com/kylpo/react-…
So I saw this in use at an employer, but it basically is a way for you to, let's drop this in here. It's a way for you to put your components on a page and try them in different states. And in React, being able to do that really cheaply and just show them on a page and show a component in several different states is a wonderful feature for sharing components in a larger team. Do they have a demo of it somewhere I can use? There's got to be someone.

19:13baipas_bag i think you might be thinking of storybook
Maybe I'm even finding the totally wrong... Ah, Bay Pass Bag. Yes, you're correct. I'm not thinking of Storybook. Playbook. I'm thinking of Storybook. Thank you. pushcx https://storybook.js.org/tutori…
I just found something that was very similar. Yes, you are correct. Storybook is the name of the thing. So you can tell it's been... like 18 months since that last job. So I'm putting it in the scratch notes for the stream page. And does it show a demo here? Construct a screen out of components. Where's a demo? Showcase. Yeah, here we go. Sure, the Guardian. no nothing so storybook man you can tell it's one react when like an unordered list has to stop and load and then it never actually loads yeah we're getting the real react experience there let's try a different one and this site is off oh it's so hard to keep docs up to date especially like external demos So the basic gist of Storybook is, well, I was going to say that it makes it easy for you to see components in various states, but the fact that I can't actually get one of these to load. So anyways, that's why I don't love single page apps and prefer progressive web enhancements. Oh, okay, here we go. The one that loads is the one that wants to look like Windows 95. I'll take it. So Storybook gives you a list of all of your components and allows you to say, okay, well, what does it look like in this state or this state? And then if you want to tweak it, you can edit it and reload up here. So it's very nice if you have a dedicated front-end team that produces components and then you, the developer, are like, what do I do with this component? Because, of course, nobody stops to write docs internally. So at least with Storybook, they can put a couple of examples together, especially for multi-components where they have several things together like here's several nested frames and you can just see the demo of okay so i want to grab this and i want to change it for these three things then i can drop it into my pr and move on with my day so i've kind of wanted to make the the discount version of this so the the discount storybook for non-spas is One template that loads partials. And renders them in various states, because we have. Like comments can be in several states where. it's a comment it's a reply it's a deeply nested reply so it's less wide it you have avatar display turned off you have tree line display turned off the comment is removed by the author the comment is removed by the moderator and then various combinations of these and if you don't if you haven't basically memorized our css and our html it's very hard to correctly edit the code that's in our story templates, our comment templates, and our form templates. That's our god objects and our forms. It's just painful in every web app. So if I made a page that was like slash storybook.html, and it just showed all of our things in a row on one page, you could tweak the CSS, reload the page, and you could see, oh, when I change that border, I'm actually changing 19 components. I don't want to do that. I think that might be useful. That's a cute menu. I have been trying to talk people into making... Here's a page with lots of examples. That's nice. I've been trying to talk people into painting a big fence, which is moving our pages over to a grid layout. Oh, neat. Thank you, whoever just clicked follower. We hit the follower goal, which I don't even remember the formula. I set, so we're just going to say if I click end and then I click start. No, I can't. Yeah, the goal thing is cute, but Twitch is so weird about it. Yeah, and now the UI won't even let me update it. So now I don't have a goal. That's fine. I don't have an API key either because they're not serious about privacy. Just so weird given the parasocial stuff that Twitch has had happen. So anyways, this flex is neat. If you're working with Rails, especially if you've had some of the more painful experiences with ERB, I think it is worth checking out. alsweigart Can't stay for the stream, but I saw your announcement in mastodon and wanted to follow. Have a good stream!
I'm playing with it on an internal. Internal is the wrong word. nogweii How do you imagine that page would be structured? A bunch of interactive buttons to toggle options, or a large list of repeated partials?
I'm kind of coding up a demo wiki. I am aware that there are a million wikis available. I'm not intending for this to be a serious project. nogweii @AlSweigart welcome!
Just a nice excuse to do a bunch of front end stuff. How do I imagine the page would be structured? A bunch of interactive buttons or a large list of repeated partials? I was thinking just a, oh, hey, Ace Weigart. I think you are the one who hit the follower goal because I see the timestamp on my dashboard and it's the same time. So thank you. and and not way to answer your question i was thinking just do the simplest thing of a large list of partials because even getting you know i mentioned with comments that there are these well you can start seeing the explosion of state space where the various attributes i listed are like five times five times five well we don't actually need a page with 125 example comments on it, but a page with six example comments on it for the most common six would be a huge value. It doesn't even have to be interactive like you imagined of having interactive buttons to toggle options. soulcuttr it's good to have a side project to tinker with new things. I also followed. They made me validate my real phone number ugh
That would be neat, but even just starting with a page that called the comment partial five times to display five demo comments would be pretty useful. Yeah. Oh, they made you validate your real phone number. Yeah, that's a gripe I have that I don't have a, what is it called? A Twitch API key because they require a non-VoIP phone number. And because I've had privacy issues, much like I assume their big streamers have, I don't have a non-VoIP phone number because frankly, none of the major carriers are serious about SIM swapping in the way a couple of the VoIP carriers are. Like heck even Google is, you know, you wouldn't worry about a Google voice number being so vulnerable to SIM swapping, but Twitch won't accept that. nogweii how do you handle mobile data, if you do?
So that's why there are no clever API integrations here. Although God, I would love to make a bunch. I think that would be a lot of fun, but no. nogweii curious about going voip-only
How do I handle mobile data? very carefully. The. I do have a cell phone and it has a SIM card, but the phone number associated with that is never used anywhere because everywhere you give a phone number will leak it. And then so if you use the handset phone number, you are also connecting it to basically every account you've ever had. soulcuttr the idea that everyone has a phone number starting to feel anachronistic
nogweii all good, appreciate the brief convo!
yeah drop me an email and i'll give you more details i don't want to i don't think i want to deep dive privacy here on the stream because it's not there's kind of nothing i can demo i'd rather talk more about code and lobsters than than gripe about the hassles i do have to like when it comes up i have to gripe about not having a twitch api key in the hopes that someone eventually will work for twitch and be like oh what if we unfucked that

28:04nogweii What's on today's menu?
all right and maybe one of these april fools i should import this and make the whole site look like windows 95. i made it look like a phpbb that was kind of a fun one that's been a couple of years so what's on today's menu if i bring the scratch up it's up on the topics here of talking about those things then i was going to get back to origin from the previous stream. So before I explain that, for any new viewers or returning, less familiar viewers, this kind of lobsters office hours, there's a fact that's under the video, you can click on it and I am happy to take questions about how the site works, how the code base works. I will try and talk you into whitewashing my fence by opening PRs to fix things. But other than that, it's a pretty chill hangout. And when people don't have questions about the site, I'm working on development. And one of the things we're working on now is some features around self-promotion because it's been, it feels like the last nine months or so we've had a growing issue with folks who are just doing self promo and not participating as part of the community and so i'm really gently trying to improve some of the rough edges around that like if you look at a new users can't submit links to unseen domains so if we've never seen bob reactproject.com a new user can't sign up and immediately submit that because I haven't rigorously done this. I see that in the internal mod notes, but I would say something like 75% of those are people whose first immediate thing they do upon getting an account is try and drive traffic to their site which is not a great feeling so I'm trying to improve that because a lot of them then turn around and go okay well I will submit the github repo for Bob's react component which is better in some ways but not less exploitative so I'm trying to to nudge people by recognizing that github.com slash Bob is different than GitHub.com slash Postgres. soulcuttr I invited somebody who turned around and did that immediately, and I was like "dude!"
So we have this origin model that I worked on on the last stream. So Soul Cutter says they invited somebody who turned around and did that immediately, and they were like, dude, and yeah. soulcuttr they were genuinely excited to share a thing, but weren't participants even though they'd read lobsters anonymously
one of the things i see is maybe the the next step from this so hopefully as a next month kind of stream because i don't think origin here is going to be more than we might finish today depending how nice the testing stuff wants to be to me i'm especially concerned about the prospect of accidentally including a remote code execution the way i started doing this string substitution but If I avoid that, this will finish hopefully this stream or the next, depending on how many interesting questions people have. Yeah, Soulcutter. They were genuinely excited to share a thing, but weren't participants, even though they'd read Lobsters anonymously. It's really hard to handle that issue. So what Soulcutter is getting at there is it is wonderful when authors and creators participate in the community. And it is normal and great that they occasionally share links to things that they do, but it is very hard to say like, well, if your first thing out of the gate is promoting your own stuff, that's kind of indistinguishable from the startup marketing hustler who just has their product they want to launch and David Price- it's the folks who I did a deep dive on this last stream and I gave an example of a user who just wanted to submit links to his own blog because he was building up towards launching a developer focused sub stack and. He got warned a bunch. He didn't change gears to do anything besides self-promo. And then I banned him. And then a couple of weeks later, he tried to sneak back on the site under another username and started all again. And literally his first comment was like glimmerings of self-awareness of, oh yeah, I submitted the Medium link because Reddit just banned my domain. I can't guess why. nogweii Are you familiar with the Public Suffix List? https://publicsuffix.org/
And I was like, I don't have to look you up on Reddit to know you did the same thing.

33:03Am I familiar with the public suffix list? Yes. It's most of what we want, but the public suffix list is pretty similar to... I want to say it was mostly subdomains, right? nogweii yeah the github usecase isn't covered
Yeah. nogweii it's not the whole answer for sure
It doesn't talk about... So... Well, halfway, you say the GitHub use case isn't covered. Half of it is. So it would cover bob.github.io, which we see a lot of, but we consider that a separate domain. So for our use case, it's handled fine, but then it doesn't handle github.com slash bob. So that is a wonderful transition into where I was going of where the last stream left off was let's... have on the domain model, let's add this selector field. And the selector is going to be a string that I got to log into my local dev instance.

34:19I got to reset my password on the local dev instance. I was tinkering with the settings page.

...28And I did something to the password, so we'll just set that. I'm not on prod, not on prod.

...42Making sure I'm not resetting that. All right, so that's set now, test. All right, that'll get me logged in. And I was editing. Why isn't that clickable? That's weird. I thought that was. Is it clickable on the story detail page? Did I break something in the markup here? I have to look at that. So we had the list of stories by domains, the suffix list, and then also the edit form. And so to the edit form, I was adding that. a field for the selector and then a field for the rewrite and was basically setting up to say that every domain has this kind of a selector to understand how to parse the domain. And when setting then a domain object, you can ask it for the origin of a URL This should probably also error out. And the heart of this, all of this really is, plumbing and validation and setup for this line here that says, okay, well, let's take the URL. Let's use the selector to regular express, to parse the URL. Like this example for github.com, it consumes the whole URL and in a named capture, it grabs this, and then we can replace with other text. so for the github.com either i'm not printing the domain correctly or i edited this domain object funny in all of our tinkering huh looks like i have to fix that validation is this one of those other we've been playing a lot with backslashes of how many levels of escaping are needed It doesn't look like that's an issue. So let's grab this out and split it into two errors, because if I'm going to split it into two errors to figure out what it's mad at, I'm just going to keep it that way.

37:59It's a little clunky to return and only have one error, but this is mod UI, and so I'm willing to let the mods wear a little hair shirt. So it doesn't start with... Are you kidding me? How does this not start with... Let's reload that. nogweii oh hey gotta love the bots
Speaking of self promoters. So I was setting up the selector.

38:45soulcuttr it looks empty?
And where was the? On the path GitHub. This must be a selector is empty, so this must be a. issue with the controller level where the domain controller isn't taking the param except it does permit it huh the the symptom there very much felt like when you forget to set a selector yeah it looked empty but did i not name this form field correctly because that could do it too

39:31So Soulcutter, you're new, so I will mention, if you catch a bug like this before I can figure out the bug, you get to be a channel VIP. So it is called f.textfieldselector, right? So this, if I inspect, God, I'll fix that scaling sometime. All right, Firefox. soulcuttr do I get VIP if I accidentally send you on a wild goose chase?
It's called domain underscore selector. Yeah, the domain is domain selector. And then in the Rails log, we see domain, but selector is blank. soulcuttr Another thing to try when logging is to print out selector.inspect
And origin replacement is blank. Do you get VIP if you accidentally send me on a wild goose chase? No. Why would I want to reward that? Another thing when trying is to print out selector inspect. Yeah, I did the puts there and I saw it. So that was the placeholder. I've been trying to not use, are these both named? That's what it is. Right, selector, selector, replacement, there it is. So let's not have place folder, because that's just confusing in the way place folders are.

41:02this well we can still have the so with that changed now i'm going to load the form again from scratch because i bit myself on that last time of editing a form that was or reusing a form that was out of date.

...42soulcuttr I don't know how deeply established this interface is, but if you require a start and end, why not automatically add it to the user input?
That is weird spacing on the help text. I don't want to mess with that right this second.

...53So Soul Cutter, this The first thing is, no, this interface is not at all well established, as you can see by me griping about the help text that I just put on. Let's grab the one I just added. We'll make sure that edit happened correctly. So yeah, the edit worked. so the answer to why not automatically add it to the user input was i wanted the user to be forced to think about the fact that their regular expression needed to capture the whole thing so that sub could let's go back to the domain model so if a previous version of this on the last stream did automatically insert those if they weren't present Actually, it might have always done it, not just if they weren't present. So the way sub works is grabbing the input string and trying to substitute the whole thing to shrink it down to a unique origin identifier.

43:22What is the reason for not putting it back?

...38nogweii While it is limited to mods, do you need to be thinking of regex-powered DoS?
Yeah, I actually don't see a reason to not include that.

...48While it's limited to mods, do you need to be thinking of regex powered DOS? Probably not. And we did, I think you brought this up last stream. Someone did. We did insert a timeout to the regex. so that it doesn't run an unreasonable amount of time, and 100 milliseconds is plenty of time. nogweii ah timeout is a good strat.
So I'm going to leave this alone. I'm going to make it dead code, but I'm going to leave it alone for the moment.

44:32nogweii Was mostly worried about backtracking explosions
So let's grab Let's do what Soulcutter was suggesting. We'll restore this. soulcuttr One way or another, I think it's going to end up important to understand the error you're seeing, because it seems like it's not what you expect there
We'll do the other version or the other end.

...50Just to make it consume the whole thing. One more backslash. Yeah, I think that's fine.

45:14nogweii dang you caught the backslash quickly LUL
Yeah, Nagwere, I appreciate that you were concerned about backtracking explosions. And yes, if this was any kind of public data, it would be bad to take a regular expression in this fashion.

...31You know, I only caught the backslash quickly because it came up like nine times on the last stream and I spent a big chunk of that annoyed at how many times I was adding and removing backslashes to whether I was doing a regular expression directly in Ruby or whether it was in a string that became, or whether I was referring to, yeah, they just, the nested layers. And then it was like HTML's nesting of a string of a regular expression It's not quite as painful as shell scripting, but it was starting to get there. So let's go up to the controller because I got that successful edit, but I didn't get a message about it. Yeah, this didn't fire.

46:42So if I have that, it's funny, I thought I stole that, putting the success on the redirect from somewhere, but maybe I accidentally pulled it off a render and you can't do it like you can on a redirect. So we'll say all this the same and save. And now I should get that nice green domain saved. Good. Domain edited. That's fine.

47:12If I really wanted a nice UI, I would have it load up a couple of live URLs.

...25All right. So a thing that was visible, there's another small bug here, was I added the display of the origin to the template, but it's also including the display of the domain. So that's going to be over in the story list detail. So if the domain is present, we'll grab the origin. I guess that regular expression is wrong and not consuming the github.com on the start. Speaking of, if I had an ICY, I immediately ran into. So it should be, oh, I don't have to. Let's just capture the part I care about. I've gone back and forth on whether the named capture should be the whole domain or just that. Let's put it in the edit. Because the origin replacement could just be backslash one, but I would like the examples to be

48:42usable for other sites. And I think this pattern of putting in the domain name is a little clearer. OK, so now these are printed out, considering them to be separate origins. So it's just a display, but it's a start. So with that working, probably was on the to-do list all right so we had that we validate the replacement and i didn't put it in here but kind of a list of oh i did show on the domain format so i have that one thing we want to have is in list detail we want to have some kind of browse stories by origin list stories so that's going to be on the home controller, of course. And then I want the show domain page linked to it.

49:53So I think now that I kind of see the outline of this code and the data model, it's probably a good time to yeah I'll check edit form well actually the edit form is pretty much exactly where I want except for being ugly so let's just fix ugly and then I get to check off that line and then once it's less ugly I'll do tests so I just grabbed that help class on the div and it has this weird spacing and I don't remember if So I grabbed that from some existing form. And it must have a different, yeah, there's the markdown help. I could put it in a P. Let's see if that, there's a lot of our CSS that cares about the element name instead of just the class name. So if I swap up the element name, we may get a very different display. I could go look at what that is.

51:17Wow. Well, there's the weird spacing. Margin top 2M. That is such a giant spacing.

...33yeah i don't know if that's worse or better now these guys are falling out so i must have oh because the slashed it i've broken the markup i had a couple of issues and such filed this morning so i didn't get to that annoying bug with where some of these pages are taking like 30, 45 seconds to load in dev mode because it's busting a cache where it doesn't even need to have a number. So how are these getting indented? Because no replies to show. This is help, help, help.

52:26I'd like these help texts to be aligned with the form element. Story box actions. Oh, I don't want to reuse that. So that width is 7m. So if I put it in a div D. I don't love this markup, but let's see where that gets us.

53:05Alright, well, I'll keep on not loving that markup. It's not something I want to refactor right this second, especially knowing that I would love to move all of our forms over to CSS Grid instead of this very float style of giving things margin left and shoving them around and No CSS variables. You just have several things that have the same width. So if I switched over our forms and overall our pages to CSS Grid, we could be a lot more responsible about things. Like I would never have had that intermediate bug where a bunch of these were hanging out in the left column. Okay. So with that, I can check off edit form. And then let's do a test or two. So this was the domain model.

54:22nogweii what's the user agent spread for lobsters? I assume grid is not a problem, but I wonder...
so we started these let's take a look at whether they run right now because i don't remember what state we left them in last week so nagwe asks what's the user agent spread for lobsters i don't know it is broader than other sites because we see a bunch of experimental browsers like what was that one that we remember the name of web positive or the one that's in serenity os someone remembered that for me on a previous stream And we do have a fair number of people who use links spelled with a Y or the I N K S. And I know we have a couple of users who use screen readers. I'm not worried about CSS grid for them, obviously, but the other ones, the, can I use for CSS grid? The reason I keep talking about it is this has been green for ages. So when was 56? Okay, so five years on Chrome. Safari on iOS, eight years. Firefox, also six years. So the support is really long-term solid. I'm very happy with that. I don't... The mental version that I have of that Rails browser restriction is kind of more in the neighborhood of when a feature is green for five years on can I use, I feel totally comfortable using it everywhere at that point. nogweii 6 year old browsers not a concern? :P
Maybe if I was working in government, I'd be a little more careful and make it 10 or something, but models domain is line 18. What do we got? six-year-old browser is not a concern not really we don't see a lot of those so this is don't need to that i'm going to split validating the selector and the replacement there actually are no validations for the replacement i imagine there will be in a minute but I don't want to do them in the same function. ymeynot45 Anyone who would be on the site would be up to date with their browsers.
So we'll do that. Don't want to have a second dot. Why me, why not? No. nogweii @ymeynot45 I'm not sure that's a safe assumption...
So you say anyone who would be on the site would be up to date with browsers. I can see how you'd get there because we have lots of tech enthusiasts on the site. soulcuttr these days I - perhaps cruelly - think that people with ancient browsers have to be used to sites not working well
And so it feels like they would be especially likely to have everything up to date, except also we're a lot of nerds. And so they'll have weird browsers. Like we've had people read the site from handheld gaming consoles, like a Nintendo switch. There was one, I don't think it was a switch, but somebody posted an article that was about how they jailbroke the web browser in their gaming console and then took it. And then I think they had a screenshot or maybe it was like a camera shot of the device and they loaded lobsters. So we see that kind of thing. And then also Aside from the really oddball browsers, we also have, let's say, very particular developers. I think that's a good way to put it. People who have very strong but very niche opinions that the very best browser was, I don't know, the version of Firefox or the version of Chrome before it broke ad blockers might actually be a good example or one of the older versions of mobile safari there's an issue especially if somebody's browser is on a lockdown embedded device like an iphone or an ipad or a kindle those often stop getting browser updates after a couple of years So yes, people with ancient browsers, as Soulcutter says, could maybe be used to sites not working well. And I share that feeling for commercial projects. Lobsters is kind of a labor of love, so I vacillate between Hey, it's a volunteer effort. Don't expect that kind of enormous commitment to compatibility. Plus, well, but we're all a bunch of nerds. Let's make it easy on nerds who do slightly odd things on a regular basis. And I don't. Yeah, so I don't have any kind of like rule of thumb. ymeynot45 Ah.. I got ya. I have an old Mac book that I can't update because the hardware won't let me up date the OS which won't let me update the browser.
just wander around between those two opinions as is convenient for the particular discussion that's exactly what i'm doing all right so let's see if the domain spec wants to run you have an old macbook that can't update because the hardware won't let you up to date the os which won't let you update the browser oh yeah that's exactly what i was talking about of i said lockdown embedded devices like ipad and iphone but that is certainly the case that mac desktops and laptops stopped getting os updates and for apple's apple has like for phones they have very competitive length of maintenance windows where they're longer than most android manufacturers but then for desktops i want to say they do like five or six years and that doesn't at all seem to fit with the turnover where now that computers aren't doubling in speed every 18 months, I see people hold on to desktops and laptops for 10, 12 years before they replace them. I am sure someone there has a chart of the hardware bathtub curve versus the cost to continue ordering new versions of Safari back to those. And the real frustrating thing there is TLS. The TLS certificates on HTTPS, those get rotated every so many years, and browsers have to be up to date. And so if the browser can't update, especially if it's integrated into the OS, you really are up a creek with valid hardware. So let's grab these.

01:02:14nogweii the push to elliptic curves is going to be painful for those users :/
soulcuttr anchors maybe?
So single soul cutter are these signals are they operators and never remember the term for a regular expression, but you were pointing out that we should do this so i'm picking on you a little trimber would you call them signals. signals. soulcuttr gosh not sure
anchors maybe oh yeah anchors is right that sounds good.

...54So yeah, I'm going to edit them out of here. And then this doesn't actually need to be a valid anything. I'm just trying to get down to a reasonably short example.

01:03:24soulcuttr I will not even attempt to paste a link, but on the Ruby docs Regexp class page, it's "Boundary Anchors"
I might put that back because I don't like having bad, yeah. Oh, Soulcutter, thanks for looking it up on the regex class that it's boundary anchors. Yeah, because they have separate boundary anchors for words and line versus start of string and end of string. And standard RB ships with some cops that make sure that you know if you're using, like if you put in dollar sign at the end, it'll say, hey, you're going to break on multi-line strings. so what changed i expected this to equal this is there even a difference get out the trailing slash okay so i don't really need yeah i'm going to delete that started that spec but Again, I don't think I need that if I'm inserting the A and Z. And if I'm inserting the A and Z, then I don't need to list it. Yeah, I don't care. We'll keep listing it because that's fine. Because it explicitly says consume the whole string. And I think of this... as like a little help of, hey, you forgot to consume the whole string. I know you meant to. Let's move that out. It's invalid for an invalid regex. Oh, there's a missing validation. So let's grab this.

01:05:41remember this interface errors on selector here we go errors yeah not errors sub email to include and then include doesn't take an array no it just takes us straight

01:06:20Oh, I did actually add that validation. So let's see what happens if I leave out, say, a closing parenthesis.

...35And then this will add to the message.

...45Let's see what that looks like. So I know the spec isn't going to pass, but I would like to see the error message. Because the error message will tell me what kind of, just give me an example error out of the regular expression class. We expect it to be false. What did I say? B underscore. Not even the failure I wanted.

01:07:18So invalid selector regex. We already know it's on selector, so that's redundant. End pattern with unmatched parenthesis. Good. That's a really informative error message. So we don't need to repeat the field name because that gets prepended. And I'm thinking of what this will look like on the edit form. So on Rails, it prepends the name of this field. So it'll be selector is an invalid regex plus blah. So we'll say that, great. So let's see if that is enough to pass the spec. No, because it expects me to have that full message. So let's just say first, and then string also has an include method. And as long as it includes the invalid regex, good. Okay, I like that. Now, Now here's the scary one, and I kind of alluded to it in the scratch of safety. I have to test that the user can't eval Ruby in the selector or replacement with Boo. So I think I saw this. I think I just thought about this, but I said, okay, so if we had ABC and I said substitute A to, let's do it in the middle, Q, nogweii but the #{} wouldn't be parsed with a string
would get aqc so that was fine that's peaceful however i could say one plus one and then i would get aq2c and that's like bad but that's very bad of oh wait a minute wait a minute we don't want people able to say yeah i want you to replace this with the contents of the password file like that's i actually it's been a couple of weeks but i had a i had a a literal nightmare that the site had a what was it it was a an SQL injection vulnerability. And I even remember it was in the search engine code, but it wasn't the whole search parser, search model code that we have now. It was like, if you imagine a PHP baby's first search engine, that level of sophistication. But it was Ruby. And someone had hacked the site with SQL injection and was doing it live as I was trying to figure out what the bug and close it and then I was shocked by this code and how did I never notice this code how did breakman never notice this code and so I just woke up like it was one one in the morning almost exactly and I was just feeling terrible because I had had this nightmare and usually like I have a nightmare and I just kind of wake up for a second I'm like oh well that was bad but I'm glad I'm not actually being chased by a serial killer and then I go back to sleep And I couldn't fall asleep after that. I just felt really bad on the inside. Yeah, Nagui, I need to see it.

01:10:40soulcuttr that is a wild nightmare
And I was wondering, like, why do I feel so bad? And I got up out of bed because sometimes... If I get up and I walk around a little and I lay back down again, it's like I'm starting over on sleep and that works. And so I got up and I started walking around and I realized like, wait a minute, the bad vibes are not just, oh yeah, it's when is it going to happen? It's when I'm constructing the string rather than, so I guess I need to say, yeah, we'll backslash it. Let's see what that does. Well, let's just call it. I don't actually need to see the validator. Yeah.

01:11:46soulcuttr I think it's safe also. You've gotten in deep with the backslashing.. is that because rubocop won't like single quotes?
So I realized this this terrible feeling was not just my nightmare, it was in the apartment. it's not rubo cop won't like single quotes it's well yeah it is it's standard rb on top of rubo cup but then. I am trying to pass strings rather than regular expressions, because we are testing. I want to test the exact path of taking user data from the form and the user data from the form is not going to be a regular expression object. So I want the tests to match that. So yeah, the end of the nightmare that we had had SQL injection was I got up and I walked around and I realized the bad vibes were in the apartment, not just inside of me. And I was like, what am I reacting to? And I kind of stood there and like, soaked in the apartment for a couple of minutes and i realized the fridge was making a noise like a groaning grinding kind of noise that was super unpleasant and i went and i checked and the freezer wasn't perfectly closed and so the humidity had gotten in and iced up the whole internals of the coil and the fan and so it was groaning and overworking soulcuttr the user input will be \A and not \\A so the single quoted representation is closer to user input '\A' # => "\\A"
i'd been asleep and so i in the you know this probably happened that the fridge didn't get quite shut just before i went to bed and then like by one in the morning i was hearing this noise and it became the basis for this bad vibes dream and so it was no fun to be defrosting the fridge at 1 1 30 in the morning but nogweii @Soulcuttr but there's no functional difference
soulcuttr kind of a bikeshed tho if you have your way of working, not gonna push
nogweii '\A' == "\\A"
was funny the way my brain picked that up okay so it's getting printed literally rather than the user input will be backslash a and not backslash back to say so single quarter representation is closer to the user input backslash a but there's no functional difference yeah yeah so i think what i'm going to do is that and then i will say soulcuttr ^ 100%
So this is one of those tests where I'm building confidence.

01:14:26soulcuttr I hate backslashes also. Any escaping characters
So I'm gonna say it on a couple of levels. Oh yeah, I see what you're saying. so yeah and so soul cutter this is this is me just trying to say regardless of what's happening here how many backslashes there are or are needed none of them should work and it's kind of clear when you see a test like this it's like okay you're just It's a peace of mind kind of test. I'm kind of throwing spaghetti, and I'm saying, no matter what, I don't even know what this is, but... Yeah. Failed, failed, and wrong number of arguments. Line 34. nogweii forgot the equals
Oh, I'm missing the... Okay, okay, then. Let's just run that one spec, see if that passes. nogweii hahaha yup
Not going not faster than me, but you're already at VIP, I believe. So that's fine. Okay. Okay. That passes. soulcuttr double quotes in the source code will interpolate #{} tho, which is not string behavior it's literal behavior
All right. Yeah. And now that I see it pass, I have some more confidence that the sub is not going to do that bad thing. Double quotes in the source code will interpolate that, which is not string behavior. It's literal behavior. Oh, you're right. Because this is going to happen... Yeah, it's not happening at the right time. nogweii yeah that's what I was trying to communicate earlier, nice @Soulcuttr
So this probably became... Well, I don't want to guess. soulcuttr it's hard to disambiguate
One of these, I would... Yeah. Yeah. So what does this test want to be? nogweii unless you actually run the Ruby parser, #{} has no special meaning
nogweii ruby parser on the input strings
Unless you actually run the Ruby parser, that has no special meaning, which should only happen on literals. Yeah, it's just, I'm nervous about sub doing it. But to do it, sub would have to call... Yeah. Okay, and then... All right, so I think I'm satisfied that it can't be happening at that level. Let's look at the Ruby regex. And I wanted to see the... Let's see, there are several modes and encoding. In the substitutions, yeah, what if you shoved one of these global variables in? I don't think you would get anywhere. Oh, $0 is quite different, returns the name of the, that's weird but harmless. nogweii can't reference the global vars tho
nogweii $1 doesn't mean anything in a string
where's the other back references special characters well that's for the regex what i want is in the replacement We have the look around anchors.

01:18:37soulcuttr Another perspective for tests might be to put a variety of fuzzing data into a text file, and have the test read the file and use each line as test data. That way you know it's not ruby interpreter, because it's input coming from a file instead of the source code
Yeah, if it wouldn't drive me mad, I would almost restrict how much of regex you're allowed to use. But I know I would never get that level of quoting right. That would be incredibly painful to code. Gradient matching, groups and captures, back references. That's what I want. There isn't any kind of like back reference that runs LS or arbitrary code, right? Backslash zero named captures.

01:19:18Okay. Sub-expression calls.

...28soulcuttr seems like overkill maybe, but hey
Yeah.

...34Okay. Okay. nogweii you can definitely make some crazy regexes, so DoS is a possibility, but timeouts should limit the impact
I think I'm, I think I have enough confidence that this is not going to be a vector for problems. Right? Because it's,

01:20:00Yeah, Nagwe, you're right about those potential for denial of service, and I appreciate you bringing it up on this week, too. I don't want to add a spec of, let's see if I can blow up the runtime of the test suite. That's a little much for something that is just make sure you pass timeout to regex. nogweii lol yeah you'd need a CRAZY regex
Actually, we could check that. That's cheap to check.

...36That would also be a hard test to maintain, because even if I said this test, I expect that this instantiation will run in, you know, three milliseconds. Well, that's hardware dependent, so.

01:21:04nogweii yup, best to not try to handle that
I swear, if this gets into comparing floats, I'm going to get a little annoyed. But that'll probably do it.

...22OK, good. So now we're just checking that nobody forgets that timeout. That's fine. It's invalid if it doesn't consume the whole line. This all kind of works. I think I'm happy with the selector. So I'm going to get rid of that. I'm going to get rid of these to-dos. I think Soulcutter's reminder of the approach I started with last week, I think that's totally correct.

...53You want me to change it to blank? Yeah.

01:22:02That kind of implies, I think I want nil, because if you make your selector empty string, you will get a regex out of it, but it won't replace. Yeah, I think I'm OK with that. All right. So new page to list stories by origin. OK.

...32So that's going to be in the home controller, which does all of these. And yes, there's a lot of repeated code. And yes, I'm okay with it because I would rather repeat stuff and be explicit about that and have an extra code site to change that's literally in the same file than try and metaprogram the heck out of this. It's actually gotten comfortably thin. I could maybe extract out the response block, but then all the rest of this stuff is pretty individual, so I think I'm okay with it. So the origin, yeah, okay. I had a note here in the scratch of, is there even, nogweii ooh, random thought, setting up WebSub (nee PuSH) for the rss feed and get realtime feed updates LUL
much of a value to having an origin model and as soon as i'm here i see it yeah so let's go back to model i mean i don't know why you're just let me when i say origin i don't want a string back i want an origin model i want that so that i can save it in the database and look it up later under that string so nagra says random thoughts setting up web sub need push for the rss feed and get real-time feed updates i think that would require that i install redis most of the rails live kind of features like are built on Action Cable, which wants Redis. Earlier this year, I had Redis in our Ansible, but I pulled it back out because of ActiveJobs. I mostly wanted it for background jobs and ActiveJobs is getting there and is fine for our workload to save to the database. nogweii websub is a bunch of HTTP back and forth between a reader and the feed provider, don't think you'd need an in-memory database
So I'm not sure what would be required to support that, but I would prefer not to add more database-shaped services like Redis, just to keep that simpler. Over in the Lobster's chat room this morning, I was talking about how much contributing to and then becoming the maintainer of this code base really changed my opinion against taking on dependencies and especially external services like a database process. nogweii boring technology club!
the value of something that is simpler to install and has fewer calls and less upgrade churn, that's been really strong.

01:25:43That looks fine. Actually, does it want to have I think this just wants to be identifier. Yeah. And the reason I'm thinking of that is the github.com github.io unification is if the selector for the domain github.io. Here, let's just do that. So instead of saying github.com, let's edit github.io new tab. So if this one was changed to say, let's grab, well, they're going to be different because it's the subdomain. So it's going to be this and then anything that's not a dot plus followed by github.io. Doesn't need the slash. Select that. So if that also replaced with that, then these two domains would generate the same identifiers for origins. Or they would raise exceptions. Validation failed. Domain can't be blank.

01:27:21That's a weird one. Did the submitted attributes not include the domain name somehow? So we have params. We have a domain object. Oh, it's not a hidden field on the form. So if we don't have a domain object, and we probably don't have a domain. Nobody submitted the bare github.io. And so that's not in the database? Yeah. Yeah. soulcuttr I've gotta bounce - have a great stream! Progress!
Let's go back to edit.

01:28:03See you later, Soulcutter. Thanks for dropping in. I appreciate you helping talk through my stress about RCE. So here we'll say...

...27then up in the controller. I don't know that I want to permit domain. I want to use it, but I don't want you to be able to rename a domain. And usually the way you do that is not,

...58allow that so wait a minute let's go back to that so it posted to slash domains rather than including the id in the domain because it was effectively calling create instead of new wouldn't wasn't it yeah there it is action create

01:29:26so you shouldn't be able to set domain because renaming a domain is not a reasonable operation and create is going to say i don't want to yeah i don't have to permit it i can just say that I think it's just in a weird state because I loaded that feed instead of loading the create page properly. Let's go back. So by creating this, by loading this URL, I implied that GitHub.io exists, but it didn't. So I got the new domain form, which is going to post to create things, which I would see if I inspected. Right on the yeah form action method is post so that's what rails does for creating things. So let's change this to say domains new. what's the. The new domain path should be. I thought there was a create method, or a new and a create in here. There's edit, patch, put.

01:31:05Do I not even make a route for it?

...26So that'll allow that. If I reload this, I should see new domain. Yes. Yes. And then I'm getting the home controller instead of The domain controller, because this route is ambiguous, and the home controller comes first.

01:32:09Where's my line numbers?

...18Oh, it's just right. Yeah, it's not separated, actually. It's right here. So that get is going in there. So if I put this first, I think that would work. Let's find out.

...42Valid route name already in use. We have two using the as, yup, yup. That is exactly the foot gun I am shooting.

01:33:03So it's the show action I'm shoving over to the other controller and it doesn't like me doing that. Between these two lines, 72 and 75. No, those are singular verse plural. You're frustrated that I did that, which it wants to route into new. Ugh, hate wrestling with Rails routing.

...47So if I had domain slash new, Yeah, it's a limitation of the resourceful routing that I have to, for new and edit, include the… Why does it even work for edit? Why does that work? Why don't I have the same hassle? Because it has the domain name in there, and then it says slash edit.

01:34:24Actually, what if I just put that back? And then for domain, I had the home controller for domain sort you out.

...47So up here, it could say, if you're asking for new,

01:35:02It's called domain edit path.

...10Yeah, I think it's called domain edit path and then it'll be or edit domain path.

...38Oh, you can't get a blank form, can you?

...46nogweii missing a colon for your id symbol
No, you can't.

...54nogweii though not sure you want to keep that line, hah
You can have a moderator missing a column for my ID. Yeah, what I was thinking was, so the,

01:36:24arh68 is this like namespace clash common in rails or what
But if you load domain slash new.org slash edit, that actually is going to render a new form for a new domain. nogweii somewhat common in my experience
Is this namespace clash common in Rails? Yeah, I mean, if you want to have string keys for your thing, yeah. arh68 is /new-domain tacky I guess
If I presented it, if I did the default routes where it was slash domain slash one, two, three, it would be obvious of, oh, is it numeric or is it the word new? Yeah, is slash new domain tacky? arh68 ya numeric ids have strength there, I see
a little bit but then that also does the same problem oh you're saying so if it was slash at the beginning new dash domains yeah i mean it could be that but boy that's tacky so i was just thinking if i presented the form and the form knew that it was a new form it could have a domain field and that is mostly useful for getting ready for domains like github.io, which given how few of these, maybe I just wanna manually create that in the database in a migration and move on with my life, but it just doesn't feel quite right.

01:38:20I don't know if you you folks just saw the two people who attempted to post about best viewers on my screen they're. highlighted as likely ban evader so i'm thinking their message was quarantined and only I saw that.

...52arh68 pffff best viewer right here folks <<< LUL
nogweii yup no messages visible to us
Yeah, nothing visible to you. That's good.

01:39:08You know, it's funny that Twitch forced Soul Cutter to verify their phone number, because just dealing with that, I kind of peeked at the oh i see the setting so there's another setting for to be a follower and it's just a question of how old is your account i don't know that that actually helps with anything because i don't consider followers to be super special so with that set let's get that back to stream manager and keep rolling

01:40:05frici it can very much help with a lot of spam
arh68 well some ppl get follow bots in waves, like constant +1
frici ^
So you get follow bots in waves. Do follow bots matter? I mean, you know, there's a slight ego thing to number go up of followers, but I don't care about it. I don't think Twitch punishes you if bots follow you, right? Like that would just be shooting the victim at that point.

...31arh68 the notifications pop up so they have to like disable them. very anti-stream .. no twitch doesn't follow
arh68 *punish
Unless you give followers special privileges that, you know, followers are exempt from moderations. frici followbots particulary as and of themselves don't matter the spam they throw might matter
Ah. Notifications pop up is so they have to disable them. Very anti-stream, which doesn't follow or punish. Hmm. Yeah. All right. Well, I'll turn that down so that the next person after Soulcutter doesn't get forced into their bad phone nonsense.

01:41:06And then this is going to be up in the ID, right? That's what the real hassle is here. So if I said domain, close that one out, GitHub IO edit, and I hit save on this one. Domain can't be blank, but I said params ID. Oh, cause the post action doesn't go to the same URL. And so it's throwing away the domain. Domain selector, domain replacement, commit save. Yeah, this form someone added for me in a PR, because occasionally when somebody, I get dumb spammers who email me and are like, your webpage slash S slash some random story links to a site that's gone. Wouldn't you like to link to my casino site instead? And I ban those folks after I determined that, yeah, they do own the domain they want me to SEO spam link to. And so that's what this form is for. How does this guy set the... What if I just said... Can't have punctuation in demand. Oh, it doesn't have the... It's probably going to error. Yeah.

01:42:59Keep on in demand. All right, so hang on. Let's put it on the to-do list.

01:43:13The answer is that, yes. And I want the edit form.

...49So now the form should get a hidden object with the not allowed undefined method, hidden, what is it called? Hidden field, thanks Rails. The rest of these didn't get called fields, but what is consistency?

01:44:14No implicit conversion of string into hash.

...23How did I use hidden field? frici its DHH, making sure you're paying attention while coding
Oh, so it wants to be, instead of being a symbol, do I pass a name and then value? Let's try that. Is DHH making sure I'm paying attention while coding? Yeah, by having everything be just a little inconsistent. Rails has gotten better about those things over the years, but there's still just a handful of them.

01:45:01So now I'm on this URL, but this is going to be a new form, which it would be nice to show.

...36Good.

...44So then the form will submit, and it'll go to the create action. The create action will do that, and then the create action is just for immediate bands. Well, that's going to have to be separate from creating domains.

01:46:09So we'll set the fields on it.

...26This is basically the update object, so let's just steal it.

...40So really what's happening here is like, if it's a new thing, do that. Else if banning.

...57I don't love doing that instead of having a separate action, but maybe I'll split it out in a minute. Yeah, I'll split that out. So where's, this has a hidden field with the box line. Class deletion. Let's add, because there won't be anything different in the params for these. It would just be a name without the other fields. And so I want to add a hidden field to explain the, no, this is the action I want. So we'll say we'll have a hidden field called, and I guess that can be a symbol.

01:47:52It's a hidden field to the same URL. Oh. That's the difference, domain bands path. That's the difference I want. So it will be to its own action. So this will become, and we'll yoink that, and add the missing end back.

01:48:31And then let's make sure that the domain, domains underscore ban, that's, that's speaking of, is it okay to make an ugly URL? That's a real ugly URL, but that's okay. It's internal only and it redirects no matter what you see. So you're not hanging out on there. Domains ban is only update.

01:49:08This needs a 2, right? It's got to say domains creating n. There you go. Thank you, standard. That seems fine. Let's see if it wants to work. So now if I save this. Blink is not a supported controller name.

...47Well, I didn't make Blink a controller name.

01:50:02Oh, I have to say post. Will that come in as a post or a patch? It'll come in as a post. So post to, come here, be bigger.

...43You know, posting the right place, but I don't know if that form was just out of date.

...53I said, grab me the form for spam site.com cash expired. So I have to wait. yeah i had a bunch of interesting issues show up on the github repo must have been yesterday afternoon and this morning kevin c who did the lobsters dark theme posted about some mobile safari issues because they use that and then A couple other bugs came up. One was a new bug. And one was, hey, I think you fixed this a while ago. And it's just stale. And it was.

01:51:47So if I hit Create and Ban on this, it's not post. It's domain.

01:52:00What is that form doing? What's the URL generated for this? The form is posting to slash domains. No, it wants to post this form.

...40There's a way to say on the form itself, where are you posting to? Let the cat in the room. Hey, buddy. Thank you. You ready for your close-up, Mr. DeVille? We'll see if he wants to hop up in his supervisor's spot, or if he just wants to lay on the mouse and make everything harder for me, which is more common lately. He has these moods, you know?

01:53:33All right, let's swap in zeal here. Oh, a few too many things.

...45Ram has a model URL. There we go. So if I say URL, I can say,

01:54:15Wait, domain ban or domains ban? Domains ban plural? Oh man, Rails. I feel like it should be singular because there's just one, but then Rails is so wild for plurals.

...43Fine. And this doesn't take an object. So now if I reload this, now I should get a form that points to action is domains underscore ban. And then the form submit has a form action of some nonsense. But I don't think we even need a form action anymore. Because now it's up in the forms action. So I'm going to delete that. Bet you there's a bunch of weird tests that are coupled exactly to this thing. There we go. Failed. Can't be blank. All right. So it's at least running the correct action now. And rather than post it's not parents ID it's coming in and that hidden field called domain. In the coupling. doesn't make me want to use arc but the coupling between. template. nogweii wrong method to edit!
and nogweii you edited create not create_and_ban
action wrong method to edit did i just change yeah i changed create instead of edit yep yep good catch you're dead right now these two are inconsistent but they want to be i don't love it resend unpermitted query or form parameter because the field pass domain as the hidden field, right? Even if I don't use it. So that got called domain underscore domain instead of being at the top level. And I don't want it at the top or I don't want it on the model.

01:57:10So don't want to just say like hidden field tag. What is it?

...21Yeah. All of these are based on the form, but if I don't want it on the, I don't want it in the Euro. Yeah.

...45Do I have to specify it?

...53I don't have to specify it, no, because it was already there in the source. But it might not be now that I'm not tied to the form object.

01:58:16Let's reload the form, see what we get.

...24So now there's an input with the ID domain. The value is, of course, hidden field tag takes two arguments of strings instead of also taking a hash. There's that inconsistency that we were just cheering about.

...51Now that's correct. And it'll get passed up as a object or in the domain field.

01:59:04Expected hash got string for param domain.

...15Why did you get that? So where's my? So the post aired out before it could print the harem. That's a little irritating because that's the thing I want to see.

...59No.

02:00:10Let's go back to the form, reverse engineer it to this guy. It's called domain reason, domain band reason. That part feels fine.

...31This is not a rabbit hole I wanted to go down, but I would like this function working. nogweii isn't this related to the before_action of domain_params ?
And if it's going to be tied together at the form, I kind of have to touch it.

...48Isn't this related to the before action of domain underscore params? It's not a before action. Before action is logged in and finder initialized, but that's not on this action. Are you saying calling domain params is what prompted this?

02:01:17nogweii oh sorry, but the domains_params method uses permit/require
zackisbob Hi
So it requires that there be the top level hash domain and we permit band reason, select a replacement that's shared between the two, which is a little permissive, but okay. Yeah. Hey, Zach is Bob, welcome. was using the username Bob earlier as an example. So create and ban. What if I just said params domain ban reason? I didn't check the application trace back to see is it even happening before my method, and it seems to be.

02:02:08Oh, I get it. I get it. It's actually... So the exception's getting thrown out of the controller, but it's actually the route. Because I bet over in the route that I...

...26I thought I maybe had a parameter here named slash domain like that. I've been trying to avoid that. Where did it post to? It posted to domains ban. So it posted to domains ban. Expected a hash got string for domain. Yeah. Really? No trace? What an interesting exception that I don't even get a trace back. or there's a JS error. Yeah, let's look at it with the Firefox. Firefox, what do you think you sent?

02:03:21Ah, so there are, that's what it is. So I named the field domain, and then because putting structured data in post params is a hack, it got confused because it created one named domain And then it wanted to create a hash, but it couldn't create a hash because it was already a string. Not a super clear error message, but I get what's happening. So here, if we said new domain, and then here, this became new domain. I'm going to have to reload the form to get that new form field name in here. But I think that's going to be it.

02:04:13It's thinking about it. Domain created and banned, real short run. Okay, so I would have broken every spec about that, but now there is the concept of creating domains rather than just immediately banning them. So we can go back to this guy, which also is way out of date on HTML. So we'll reload that form and throw away the code I wrote. Thank you. Thanks, Firefox.

...49So now this guy calls domain with the params ID. When it comes in from the route, it's called ID. What got posted up? So it's in the path. Now here we go down here, we're posting the slash domains. if we're posting to slash domains it's the kind of the inverse of the previous issue with create and ban where this hidden field tag maybe it's because i'm doing form with and it initializes the domain object a little different but or it's putting domain in or not here did it put domain in the selector no it didn't or if it did the domain params filtering tossed it tossed it silently instead of throwing a 400. i don't feel like i really understand why it's throwing this but i feel like if i match the way it happens in the other one, I should be able to match how I'm looking it up.

02:06:37I'm gonna check the name of the hidden thing before I submit though. Authenticity token. origin select it's just not present did i not reload did i not save no i saved oh that's a fun one so i named it but i didn't say equals so one more inconsistency is if i'm not using the form object or actually maybe that was even This should have been equals hidden field. Man, this distinction between execute arbitrary Ruby or execute and print it, it's a little clearer in Flex too. Not that I'm going to port lobsters to Flex anytime soon. That would be such a huge amount of work. All right. And the mouse cursor is wandering because the cat has started sitting on it. So thank you for contributing.

02:08:16nogweii pay the cat tax! :P
Now it's going to go into the main domain thing and it's going to complain. So I'm just going to preemptively rename this to new domain. Do the same thing as the other side rather than fight around with it should be permitted on new records.

...42okay so i already actually left that in on accident so that worked out nicely so this one wants to become named new domain so i don't have that same painful hash first string thing pay the cat text no he's not so when he's down on my desk i can't actually point the webcam at him because it can't point down His usual spot is on top of the filing cabinet over my shoulder, and if you would like to go back up there to his usual spot, I have a webcam that's angled to show him, and he showed up in the second or third stream briefly. So if you want to dig back, there is a cat photo of him in the archive.

02:09:41Come on, sir. All right, back into my lap. Big feelings today. Domain edited. Good. Good. I mean, I'm almost suspicious of it working at this point, but good.

02:10:01Okay.

...06Yeah, there we go. And so now if this one said, main.last.origin for, we'll say, zachisbob.github.io, instead of just Bob.

...29It found it. But then the origin return, oh, it's not .com. It should be .io. Table lobster's origin doesn't exist. Hey, what great progress. We tried to look it up by the identifier, and we got an exception. Because I don't think I've even run the migration that was grading things. So let's go look at that migration.

...58Oh, I must have run it. Or I ran it in a broken state, because we've had a couple of these migrations where they run partially, or I revised the migration. So I'll probably have to just redo. Let's just get that going. But then taking it down can't pass.

02:11:31Come on. Let me just create a table for it to delete when it redoes.

...43Because the other thing I could do is manually go delete the domain columns off a domain and the schema validation. But it's easier to just make a table for it to delete. And then we get the right one created. So it references a domain. It has to. It has to have an identifier. Then there's a timestamp and then does origin do anything? Yes. It lets us look things up by identifier. Yeah. So let's go try that in the console again and see if our new, Hmm.

02:12:34Let's grab that out. Looks like the replacement field didn't get set correctly. Neither did the selector. What?

...52Yeah, those fields got set to nil. So that's why I'm getting nonsense back. All right, so let's fix whatever happened there.

02:13:08called domain update, domain params.

...18Let's jump back here. I'm going to delete that. So I could test the same code path. Good. And then let's go back to . Gonna pause for a second to sneeze.

...59Alrighty, so, yeah. The, joys of having cats when you are slightly allergic. I must have, pet him and then touched my face. So then I tend to have a mild sneeze or two. So we have the new domain that's set. We have the domain selector. And we have the help and replacement.

02:14:33So if I save this, I expect it to say domain created. And then I'm going to go inspect the params over Yeah, over in the Rails output, this should show it's cut off by Vim. This shows params are empty. No, that's the get because it redirects after it does it.

02:15:01Yeah, it shows domain with the selector and the replacement. And then the domains controller says, that's weird. That's so weird. What if I put a debug in here?

...28I don't usually reach for the debugger, but if I have to manually load and destroy domains and then reload the form, I want to... not do that 100 times. All right. Yeah, I guess I did, Marils. Let's set it to Debugger.

02:16:11All right, wrong window. All right, reload. All right, so domain params is an action controller params as we expected. And we have a domain object. The domain has that stuff set on it. So if we say domain.save, we get true. And actually, I can see the query up here. Oh, it's the update. I'm calling the wrong method on the model. And it's calling the, what is it? Is it update attributes?

02:17:14If I This doesn't want to call create bang, it wants to

...46domain update should so i'm trying to update the in-memory model with the new attributes from the params and save it in a separate step so i can wrap that in if but then so t equals

02:18:29Oh, if I didn't typo. So de-update is the active record method for disregard everything, go save. Instead of being the one that just updates the attributes, is it update attributes? I thought that was the database one. Undefined method, yeah.

02:19:29I guess I've just been saying if and branching on that.

02:20:10Let's go look at the rails.

...17I don't have the guide.

...24It's in the action controller. All right.

...47Update bang. Update is also going to be the one that hits the database directly. I swear there's one that works on the in-memory model.

02:21:33So what I'm trying to do is if the replacement, so my hassle is I want to find or create, initialize an object, but I can't really call update until it's persisted. And I want to be able to report any exceptions.

02:22:08There's a one-liner for this I'm not remembering. That's just very verbose. So this will fail if the validations will fail, and then that'll kick me back to the edit form. And that's what my concern is.

...39Because that'll handle the case where... Actually, the right way is I want to handle the case where you try to create a domain that already exists. That should blow up nicely. That should fail for uniqueness.

02:23:14So throwing that out. All right, let's get the form back up here. And you must have loaded out of the database. Did I create two? I don't have a uniqueness constraint on the domain, do I?

02:24:17We really don't have an index for it, right? A string, we have an index, but the index is not forcing it to be unique.

02:25:03You know, speaking of inconsistencies, it bugs me that it's db migrate, but it's db rollback instead of db migrate rollback. Just treat it as a namespace, put them all under there. All right. So running it down and then I can add.

...31Right, that's the syntax. We might have to drop the existing one.

...49See if it complains.

...55Oh, wow. There's already been a bug. There's bad data in the database.

02:26:36How many?

...43arh68 you kinda doubled it
Oh, it's going to say like a million, isn't it? arh68 d1 < d2 is like the way, no
You kind of doubled it. What did I double? Double, double Toriel and Trouble? Oh, yeah. I see what you mean. Yeah, I should have said less than because it's going to print both sides of each. Good call. Thank you. You know, I was bopping along and one of the times I grabbed the last domain and looked at it, I saw the ID number and it was a fairly high number, like a quarter million. And I was like, oh, that seems a little high. And I almost commented on it, but then I just wanted to keep moving instead of thinking how many domain records were in the database. But we get so darn many links to like github.com and other top sites that it just didn't totally snag my attention as an impossible number. And speaking of not having an index, this is a weirdly slow query.

02:28:06got a peek at the schema for a second that's funny we don't have an index on the domain string yeah we don't so this is creating a new index where there literally isn't any all right so it is exactly two records that's a lot less bad than i feared however i should have included the ids

02:29:05So this one, so codingunicorn.dev is kind of infamous. That was this weird guy who, weird in the pejorative sense, his name was Edward Sizovs and he ran some conferences and he created this entire alternate persona of an attractive young woman named Coding Unicorn who had an Instagram and he was doing this thing where he would start his events and he would have the coding unicorn or I think also another woman that was also like, there might have been another two or three fake women where he would list them as speakers on the site. So that when actual speakers he invited came and looked looked like he had more diversity and then he would have the fake speakers silently drop out shortly before the conference except coding unicorn wasn't just a fake name on his conference page it also was an instagram account that was active for years this blew up i don't know maybe two years ago two and a half years ago but i had banned him arh68 that's a strange kind of energy lol idk
God, like five years ago, because someone pointed out it was some weird sock puppet. And I looked into it and I was like, oh, yeah, that's this is all this guy as a sock puppet. And I banned him and I banned his coding unicorn account. It was so like I sort of get the conference scam. I don't I wouldn't excuse it, but I understand what he was doing there. But I don't know why he was running this whole fake persona on Instagram for years. not just associated with conference stuff, but for years and years. And then a couple of years after I banned him for this, some speaker at one of his conferences noticed the scam with zackisbob My phone died
people being on and then off of the speakers lists or something, and they posted, and then, you know, the whole world jumped in. I don't know this other one, AaronHawleyLiveJournal.com. I think that's a totally innocuous site. Zach, it's Bob, your phone died. Welcome back. arh68 hello from the afterphone
So I'm looking at this, Aaron Hawley. arh68 those IDs are adjacent, .. hmm
there's just one blog post a couple of years ago i really don't know why we would have two domain objects because that's there's one story and two domain objects i wonder if that is someone tried to submit a story and it created a domain and then the story save failed the ids are adjacent yeah that's really conspicuous so

02:32:18zackisbob I'm going to eat vinegar and grapes
So this one, it's so odd. There's two, but there's only one story. Maybe one of them got moderated away, and I'm not seeing it because I'm not logged in on that browser on the test data. I'll look at it off stream. No, there's still just the one. OK.

02:33:05frici the story deepens 🤔
arh68 balsamic vinegar ? ChefFrank never done that combo
zackisbob It's good though
frici must be
all right so we'll grab let's look at both of them two stories but even as the admin one of these is going to be deleted right and it's got to be the one that doesn't have 2011 in the title

...37frici the one you saw earlier did have 2011 iirc
yeah so this second one was deleted and yes richie you're right i can still see it off stream the one i deleted does have 2011 in the title so i guess i'm going to have to add this to the migration

02:34:16zackisbob bewmBorgor1 bewmBorgor2 bewmBorgor3 lite snack
I'm trying to think. Let's do a find by. So I'm also thinking of this is going to run in the context of sister sites, and I would prefer it not blow up for them. So I'm going to find, let's just fix these individual stories. Yeah.

02:35:01albynton It looks like the media stories about Coding unicorn are from November 2023, about a year ago.
Elvington, yeah, I was thinking it was two years ago. Maybe it's only a year. I could just say a story.

...25zackisbob Ima eat you
And I think here I'm just going to set the domain of the first one.

...39All right, so that cleans up that one. And now let's take a look at coding unicorn.

...49So these, yeah. So like this Aaron Hawley one, I can tell myself a story that someone previewed a story or tried to submit a story. The fact that they're adjacent like that, but these are separated in time.

02:36:15And neither is deleted. arh68 only 1 domain there
albynton I also would have sworn it was longer ago, I had to check. Time goes fast.
That's so strange. I kind of don't want to know the code path. Oh, you're right. Only one domain there. Good eye, ARH. Yeah, so we had two, but only one of them has...

...47Only one of them has stories, I bet. Let's double check. Because I ran this check for the LiveJournal domain.

02:37:02All right. So I'll just delete this one.

...14Let the cat back out of the office. So again, with an eye towards the sister sites that are going to run this,

...56There we go. So we'll say, OK, if we actually find that extra one with no stories, just drop it. This guy will just combine them. And then we can create the index. So let's see if that migration runs. So it's funny. nogweii you're not cleaning up the 2nd LJ domain
I thought this origin thing was going to be all new code. And instead, we're, what, like three layers deep on yak shaving of fixing the domains. Not cleaning up the second LJ demand? I'm not? Well, clearly I'm not, right? Duplicate column selector. What blew up? Add origin line 3. Did the migration start running and then fail and leave my database in an inconsistent state?

02:38:49Oh, you're right. I'm not actually deleting it.

02:39:03And let's copy and paste that name because there's no way I type a random domain correctly. Oh, you were reverting the wrong thing. I got to cancel that. All right.

...29Good catch there, Nagwe. Thank you. How did, like, half of this migration run?

02:40:10Okay, so now you know that the one I'm trying to run didn't run.

...23Cannot update or delete, delete or update a parent row. Foreign key constraint fails.

...38nogweii there's a story that exists that references the domain
I guess what's happening is the Rails migration isn't running in one transaction. There might be something happening where MariaDB doesn't support running a DDL and a DTL. Going to get tired of running that.

02:41:31Oh darn, it doesn't print me the SQL.

...42Of course, at this time, this part of the migration should have run. So I shouldn't be able to find any duplicates in the domains table, right?

...57Let's see if I find any duplicates in the domains table. Because if I did, it says that I didn't get the part of the migration that was cleaning up the data correct. which is very possible. I was pasting around a whole bunch of raw ID numbers, and I don't have them memorized or anything. So that's going to take 60 seconds to run. We'll just give that a second. And look at this. Come on. So... This wants to validate. That part's fine. So we tried to find the migration with that bad domain and just toss it. And then we tried to find the one story with the short ID, set the domain.

02:43:01Yeah, I remember these were adjacent.

...12nogweii oh
Now, why did this not run?

...21nogweii not saving the story
Oh, do you see it not saving this? You're not saving the story. Yeah, what if I said update domain? Yup, yup, yup. I mean, as long as I was just getting mad at that update method, it's fine.

02:44:16Hey, there we go.

...24And this domain fix, I don't want to break it out into its own migration, but it's separate from this origin stuff, and it should have been in prod for a while. It just doesn't feel quite worth breaking out to its own PR. or to its own patch and bringing that off the branch. Maybe if I was already using Jujutsu, where it's all about make a pile of changes and sort them out later, but I have not yet gotten the hang of that. I haven't even tried. So hold on.

02:45:15I'm doing the thing where I add something to the to-do list just to cross it off because I want a record that I did that. And let's see, where was I? We were looking up origins by identifier, I think. No, we were checking that I could create the github.io one.

...44Let's make sure it's not already in the database. It is. Let's toss it. Actually, yeah, it got created without the correct selector and replacement, so I'm going to just delete it. And now let's see if the form wants to behave.

02:46:22So it says it was created.

...33Ah, and it was created with the correct selector and replacement. All is right in the world. Yay. Okay. That was a long way to go for a drink of water. So there's domains new. And this part is fixed.

02:47:06I think the next thing I want, I can close these extra tabs out. The next thing I want is for this story or domain page to include something about how there's an origin.

...53Oh, and you know, that kind of immediately calls for a way to browse origins by domain.

02:48:03Yeah, do I want to print the selector? Or do I want to print that there are multiple origins?

...14So I added the hasMany.

...24So I'm okay with it being academic.

...40Do I want to print them all? See if I print them all, it is fine for most pages, but literally not GitHub because there's going to be thousands pretty fast. Oh, there we go. That's another thing to do the migration. needs to create origins from existing domains. Let's put that at the end of the list.

02:49:20Not sure what kind of UI is interesting there.

...44punt on that for a second. GitHub.com up. Oh, I already had it up in the first tab. So here is not printing all the Origins. I thought I put that in.

02:50:09I did put that in. I reset so many things that maybe I knocked the thing off of GitHub.com. Let's look.

...29Yep, they got reset to null somewhere along the way of, oh yeah, me dropping and recreating the columns over and over and over. That's what dropped the data.

...42So we'll put that back.

...58Cache busting.

02:51:32Who dares raise an exception? AppViewsHomeIndex. 970. So that's calling into this domain object.

02:52:00Unknown column. Didn't I rerun that migration? This is probably just that I typoed identifier somewhere, or I left out the column.

...31all right so if the if the table exists this column should have been created it's different or no Doesn't have to be unique, because GitHub.io, GitHub.com are deliberately trying to smash those identifiers together.

02:53:35Yeah, that's so strange that the migration ran, and we got the table, but I didn't get the fields on the table. How is that even possible? Did I get some basic part of migration syntax wrong?

02:54:25No.

...32That's so weird. Let's revert that. So if I roll it back, it dropped the origin table and the other thing. Okay. And now if I migrate, and this should run clean because it's already deleted that bad data. And for the sister sites that made it, okay, so we have a create table origin. And if I desk origins, got nothing what oh it's origin versus origins all right so okay so here i said origin and rails was like yeah but how about plurals because the model is going to go hit the other thing and some failed migration somewhere along the way must have created an origins and then i manually partially reverted it and i had to do that because the transaction cleaning up the data ran separate off it's one of those things where like i've struggled through it years ago and so i've seen this kind of nonsense before but i always wonder how junior developers ever deal with that kind of stuff maybe they just get the gray hair to become senior developers and that's just how I am, but some of those things are so painful to see like a difference between singular and plural.

02:56:13Let's look at the database.

...19The field is there. Let's reload this.

...28nogweii the few mentees I've had, I've had to just simply explain it as a "hard and fast rule" without mentioning the ways to violate that rule
Better.

...34Few minutes I've had, you've had to simply explain it as a hard and fast rule without mentioning the ways to violate that rule. Oh, the rails use plural for tables. Yeah. I was talking to someone, I don't remember who now, but someone at Madison Ruby earlier this year nogweii yeah, as a "thou shalt always"
And they were joking about creating a gem called Ruby on Rail. nogweii LUL
And all it would do would be to default everything to singular and help you incrementally update a app to just make everything singular. And I think, I think their big design question was whether it should be called Ruby on rail or whether it should be called monorail and both are great names and both would be an improvement to this kind of foot gun in rails. So I'm not seeing the identifier. Cause of course I rolled back the migration dropping these data columns. So I have to put them in again. Hang on. Let's delete the invalid ones. And these two are not equivalent.

02:58:15Why do you say paper jam when there is no paper jam?

...25Column is called identifier. And now you're saying unknown column origin.identifier.

...41arh68 identiFER
arh68 fier
I don't even know at this point.

...50It's just a typo. It's just a typo. How ridiculous is it that I caught a different one-letter typo bug that was not even the one-letter typo bug present here?

02:59:19arh68 identfier isn't exactly it either ...
So I'm changing this to initialize because I think the migration... I'm going to have to run it again. nogweii more typo LUL
Identity... There we go. Autocomplete. More typo. Yeah, that's... I guess it says that I've been streaming for three hours and now I'm starting to get a little punchy. The... It's funny. I'm not as wiped as I am by the first time I did a stream here. What was that? Two or three months ago? I finished it and I sat down looking out the window and I just stared off down the block for an hour just kind of vegging because i was just so fried it was like when i've given talks at conferences i come off the stage and i feel like i've been hit in the head with a brick where i'm just just so wiped and it's getting better like after the last couple of streams in the evenings i've been fine to cook dinner or play a video game or hang out. I haven't jumped into having coding, but the performance aspect of streaming kind of runs me down a little. So this wants to be like story.findEach.

03:00:49Yeah.

...58It doesn't need to be find even. So let's loop them and then say... It includes plural.

03:01:17Let's...

...32I guess what I want is the inside of this code here.

...40Do I want to find or create? Yeah, I think I want to find or create. Let's put that back. Because if I do this, I'll get an object. It'll be in the database. It'll handle dupes. I don't actually care what the identifier is. So that says where. Oh, OK. Thank you, standard RB.

03:02:35This is going to create nothing because none of my domains are going to have selectors and everything yet. This is a big no-op. This needs to run whenever selector changes. And it needs... Yeah, so... I spent so much... time on temporal coupling of when is this code going to run in what context so here we set the selector it really wants to be a hook is it after save yeah

03:03:51I don't know where this code wants to live by order, but... What's the API here? I want to say if that one attribute changed... Where'd it go? What did I do with zeal? Touched on this for... some other code the other day.

03:04:33Changed question mark. But I want not changed attributes, not changes. There's a way to say what's the specific Did this specific column changed? Good grammar there, Peter.

03:05:13frici Need to head off, take care folks and catch you next time 👋
Changes applied called pattern name will change.

...28And then in the callback,

03:06:05so if either of those changed we have to touch every story on the old version or the new one oh fritchie i hope i'm not seeing this 10 minutes later but thanks for hanging out and hope to see you next time redundant because it's the last thing all right so i want to say

...36all the stories for this domain.

...50We want to go through all of them. I think the

03:07:13I think the stories table needs the origin field now.

...21Let's add reference, right?

...47I think I could just say origin and it'll know it's a.

03:08:01Just mad because I'm in the middle of an edit on domain. Local variable A.

...21Oh, I haven't saved the file. So what I'm seeing on screen doesn't match. So I want to loop over all the stories on this domain and say that the story origin equals the origin method. or this URL. If they have a domain, they have to have a URL. I mean, that's not actually expressed as even a model validation. We'll see it blow up or not. But this should force all of them to reevaluate their

03:09:22their origin. So this handles both the case of something that wasn't on the origin should now be and something that should now be on the origin no longer is. That all seems fine. It's going to be slow for GitHub, but that's OK. And I'm calling findEach because that It's not in the name, but that we'll find in batches. And so this finds them 1,000 records at a time, which we're going to want Just to check.

03:10:16Yeah, 7,000. I mean, the migration would... Well, when I create those on prod, it would run, but it would be a little slow.

...31Yeah, so what? It's almost exactly 10K. It's not bad.

...49So that's all fine. And then when a story is saved, it also has to pick up its origin.

03:11:13I think that happens in URL equals, right? Yeah, call set domain.

03:12:06One more sneeze for the cat. That's actually, I mean, there's so much magic happening, but it's actually nice how short that is. Speaking of temporal coupling, this method assumes there's a URL because it sort of knows it's only called from one place. Ah, Rails. Implicit knowledge.

...46So this isn't assign origins so much as it is update origins.

...58It would be assign, because I was thinking at first it would only run on create, but then that has to happen every time the selector or the replacement has changed.

03:13:14And if the URL doesn't match, this probably wants to be a validation error. So we're kind of pushing the limits of Rails validation. But I would like to express, at the point you are editing a story or i'm sorry if you are editing a domain to update the how do i put that don't need that but so

03:14:09And then when editing, selector or replacement, fail validation if a story URL isn't matched. So I did this part. But this is one of those I almost want to see in practice. I'm wondering if I should have it force me to consider any kind of corner cases when setting up a domain that feels safer. It does mean that saving a selector for GitHub would have to run against all What did I just say, 7,200 domains in the database? So that save action is going to take a moment to load all of those stories out of the database. What I really want to know is, does that match run cleanly

03:15:54So here it kind of wants to be stories.pluck the find one or is, I think it's pluck. Just find me the string rather than, and I'm trying to avoid, yeah, from each element. So this will give me back an array of URLs.

03:17:23zoom i'm trying to get it that like so there's if i write the selector like this anything that's not if i write what i actually had i'm poking the browser off screen just to grab that sample so a corner case here is Really? You're going to do that? There we go. Linux clipboard. That's not even the right. Come here. So problem with this regular expression is. It's not going to come up with an identifier for the bare domain. So Bob is going to become github.com slash Bob, right? What is github.com going to become? And what is github.com with no trailing slash going to become?

03:18:56they're both gonna fail to capture something, which is that branch with the error out.

03:19:13And I don't know if that's okay or not. So if you submitted the root URL for a domain with multiple origins, does it just wanna, error out does it want to force you to consider that in which case it's got a change in this would become that and then the replacement would become i'll just kind of space it out the replacement would be github.com backslash one because then the trailing slash is there then the bare GitHub and GitHub slash are two different things? Hmm. also trying to get at the error of if we left off this dot star which would be an easy error to make if i leave off the dot star then in production that kind of turns into github.com that would turn foobar into foobar instead of just foo So there's a lot of... No, there's two corner cases. Three? Three corner cases.

03:20:55The domain with no path. Bain with slash, but no path. and extra stuff after identifier. Look at that, still can't spell identifier.

03:21:16And I guess what I'm saying is I would like it if the validation forced you to think about these. And the only way I know of to force it is to look at all the data.

...36And this one, I almost can't catch this one because you're not going to see that until you've saved. Let's bring this over to Scratch because it's been going for a minute.

...57There we go.

03:22:05So the problem is there's these three corner cases. And here's our table.

...36And then I guess is this good or bad? Space these things out some more.

03:23:07nogweii spreadsheet time :P
Oh, that's not even the mistake. I mean, it's one version. Spreadsheet time. Yeah, I mean, BIM is a spreadsheet if you squint, right?

...32So if we capture that, and then the replacement is slash one. This was slash.

...55So this one's good. And if we have this, this is just me duplicating things, right?

03:24:18oh it's the one i want to force somebody to write this longer one yeah it's the corner cases of so does the right thing with foobar does do the right thing with github does it do the right thing with github zackisbob I'm eating vinegar grapes and hot rods GlitchNRG
And you know, Nagoya, more than a spreadsheet, I kind of want this to be a table test so that I would actually be running this code. But the wiring of hooking this up into the test suite instead of just thinking through it is so tedious. Hey, Zach, I appreciate you dropping by, but Please stop talking about what you're eating. It's not relevant. And if it was one message, I wouldn't care. But if it's 20, just stop. So this one, I guess this is good. Then we consider the root a separate origin. And at least it's the same one. where if I hadn't put the leading slash into the capture group, we would be treating these two differently.

03:26:06Let's say mistakes plural.

...15It's just going to fail to match.

...53these are and this last guy i already handled that's a longer so i feel like i'm i'm building an incredibly elaborate foot gun because what i want to express is yeah the thing right after the slash And I've already gone through like four versions of this regular expression, just developing the feature. And if I've created a template, because most of them are going to look like domain and then the thing after, you know, subdomain.github.io is the odd one out here. I almost wonder if I should back a lot of this out and just say, What's the first thing after the slash and give up on github.io. Like, is it worth all of these gyrations and the possibility of getting these so wrong, but it can't just be, well, it could be after the slash. Cause even Twitter did slash at username. And if we consider the output identifier at food, that's fine. I don't mind having that extra syntax creep in there.

03:28:29Lobsters is the really ugly one because we have the, we don't need to handle it because people don't publish under their profile, but our URLs used to be, and they've changed to, for style points, Because I grew up with the mod user on Apache. And so this is not quite the first thing after the slash. But you can handle it with a full regular expression if you're willing to use the pipe character.

03:29:24So maybe the help text wants to say, or you want your selector to look like this. Let me cut down on the visual noise here, especially because the code adds it.

...43It's one of those things about regular expressions is they're already noisy.

...53So given that this is a fairly uncommon feature, Maybe it's okay that the UI is bad. And given that it's okay that it's foot gunny, because it's only moderators. And then it maintains expressiveness.

03:30:27I guess. yeah this one this won't be right this one would actually capture the slash Or no, it would fail to capture the slash because there aren't characters after it. So the output would be nil because it doesn't match. And the same for the bear domain.

03:31:24So is it good that you can get I guess what this question comes down to is, put guns aside, is it good that it's possible for a domain selector to not match?

...51Is that invalid?

...58Root domains, what's the identifier? Because if it's just maybe the fallback wants to be,

03:32:30nogweii I wonder if showing the last N entries in a before/after table as a preview of the selector & replacement would be helpful
You wonder if showing the last N entries in a before-after table as a preview and replacement would be helpful? Oh, I think certainly. I mean, given how many foot guns there are, that level of fast feedback is almost required. Yeah.

03:33:26Oh, and you point out.

...39That you do want to see what's the old one and get you and what's the new one. And then, you know, maybe even. Highlight change rows. nogweii basically, your ASCII table in HTML
that really would be a vital feature. So I think what I'm getting to is if your regular expression doesn't match. So it's brutally hard. Basically my ASCII table in HTML. Yeah, actually, it's pretty close to that. Good thinking. So what I was thinking was like, then if we wanna handle this whole slash and not slash business, This almost has to become capture the slash as one group and throw it away and then make this backslash two. And that's so complicated. Whereas if the fallback is this fallback of you just get

03:34:52an identifier that would be whatever the domain value is set to, so github.com. nogweii how does the dupe prevention code treat a trailing slash? Relying in URI.parse?
That seems good. It's less special casing because you get back a string so you know you get back an origin. So then all origins... Nagwe, are you saying dupe prevention we've added here or the existing dupe prevention for story submission? nogweii the existing for submission
Almost nothing relies on URI.parse in the code base because it's not lenient enough for us. The existing first submission? Yeah. So we have a concept called normalize URLs where you can see it in extras URLs. We take in a URL and we do a bunch of transformations in it to normalize it. This code was kind of inverted. It used to generate alternate version, or it used to generate like a select, a really giant hairy select that I'm pretty sure had an injection vulnerability where it would create variant URLs and see if any of them were in the database. This one says, well, let's strip off a .html, let's strip off a trailing slash on a domain. I mean, this could, nogweii right, follow similar rules
All the domain origin stuff could run against this normalized URL and it would handle that case of trailing slash verse not, I think.

03:36:34And then there's some very site-specific features in here like we know something about how rfceditor.org generates many URLs for a single RFC and we know how YouTube generates many URLs for a single, nogweii not sure if running the method is a good idea, but we already have established a pattern with the normalization
video so many we've had so many dupes for those couple of sites arcs archive rfc editor and youtube origin is almost the same thing as normalizing not quite yeah i see where you're going there let's look at the If I have a console, if I set a, where does that land? Is that on string? Utils. Let's just normalize. It always takes a URL. used to be called normalized underscore URL. Yeah, so it strips trailing slash and it strips protocol. It would simplify regular expressions to not have to grab the HTTPS.

03:38:23I feel like I don't want to call normalize URL and pass that to find the origin because I don't know that I could explain that to the user. So if I take your idea, your very good idea here of showing people what's going to happen to the latest URLs they submitted or That have stories submitted for them like that's very useful, but if I have to say, but you're not quite running on that you're running on the normalized URL. I could show them the normalized URL, but then I have to explain where that comes from maybe that's okay for the small user base and i'm just looking for problems hmm. hmm. So using the URL, all right, so let's put this system.

03:40:40nogweii ehhh. not showing the normalized URL would lead to more confusion IMO. If it will be used, mention it.
I kind of want to sleep on that one. It's complicated enough that I feel like I'm not immediately seeing all the pros and cons. nogweii 100%
But if I stepped outside, walked around the building and came back in, I would probably think of another pro or con or two in a way that is really hard to do when I'm keeping up powder.

03:41:08So if I showed this ASCII table

...15Especially if the, yeah, you know one thing, always show root domain two rows with root domain and with and without trailing slash. What if I just put it in the UI? Then that forces the user to think about it and deal with it.

...47So then the other question is, if we give the user that fast feedback, is there even a need to have all this validation stuff I started writing of, do we need to consume the entire URL? You know, if I show you the last 10 store URLs and what happens to them, there's the possibility that store URL number 11 or store URL number 94 would have an error where it's not matched. What if I showed you that? What if I showed you three recent URLs but then also show any URL that's not matched. So on the back end, I mean, this fast feedback section that's going to JavaScript to the server is gonna wanna have a progress thing, because when you're editing the selector for github.com, it's gonna go run on all 7,200 URLs. But if we show any that are not matched or show first 10 URLs that are not matched, that gives the user that feedback. And if that falls back to you get an origin that is just the bare domain, as opposed to a nil, that handles everything. Then we're saying there's no special case for nil. There's no special case for URL failed to match. So there's fewer exception paths through the code. Yeah, I think this is one of those places where talking through what's the UI going to be really influences the design for the better. So that says that this method, I don't need that old thing. We'll call it valid. And then here, we'll say origin.find or create by. I think that one's redundant. I only need the cell phone assignment.

03:45:08This is partial in the functional programming sense, which is maybe not the clearest comment, but it's fine for a first draft. Yeah. Yeah, I like that.

...29That really collapses the special cases down.

...48Thank you for pair programming with me today, Nagwe. You've improved this code just talking through the design in these corner cases. I really appreciate that. And by that, I mean your attention and your insightful questions and UI contribution.

03:46:17nogweii if only I had a job doing that, it's fun :)
Okay, so let's kind of move all that notes. If only you had a job, what, pairing? I'm trying to remember, Inagwe, were you a university student? You never have to answer a personal question if you don't want to, of course, but pair programming is a very common part of being a professional programmer. That's why even things like rubber ducking are valuable.

...59So I want to keep this. Let's keep this. nogweii nah, I'm a pro. devops historically, laid off a month ago.
I'm starting to think about wrapping up because I've gone almost four hours. The functionality is in a pretty good place. bluwumeaway I don't think i have ever had pair programming outside of college. :/
nogweii @bluwumeaway oh no! that's one of the best things about programming
These can come back up to the... Oh, Blue, I'm sorry to hear you haven't had programming outside of college. I worked as a consultant for years and a lot of the time we were adding to other teams. Oh, and Nagui, I missed your answer that you're pro DevOps. I'm sorry to hear you were laid off a month ago. You're clearly competent, so I do hope that you'll be able to find a new job promptly. bluwumeaway I agree, my current company just does not have any dev culture.
If you would like, my email is on my blog. You can send me your resume and I'll reach around to folks I know and introduce them. I can tell them honestly that I have paired with you and you have been insightful. nogweii I would very much appreciate that!
I don't have a huge number of jobs in mind because we seem to be going through a, oh man, where's that graph, that chart?

03:48:32Fred is, no.

...38Fred is a tool of the United States Federal Reserve. And they have a chart that is... Oh, great, Nogwai. Please just email me your resume. It'll take me a minute to come down from the stream, but then later tonight or tomorrow morning, I can look at shopping it around. And do include some kind of notes about what you want. Like, do you want to be at Big Tech? Or are you in Beggars Can't Be Choosers? Oh, also your... shoot what's the word residency requirements like if you're only looking us or only looking eu and then i guess the other thing is tomorrow will be another new quarter and we have a quarterly job threat on lobsters nogweii oh shit is it time already?
Yeah. So it's not huge. There's only, well, 33 is actually higher than I expected for the last one, but we'll have a new one tomorrow. And if I would, I kind of expect that someone will post it even before I get up in the morning because somebody tried to post the Q4 thread like two weeks ago, three weeks ago. I think they thought September was the start of the quarter. So anyways, it's okay if your answer for what you're looking for is beggars can't be choosers because there were a ton of jobs. Oh man, 2022 was so... I got like inquiries from recruiters almost every week and that's certainly fallen off with these jobs. It's a shame this data doesn't go back a couple of decades. But I would really like to see that and yeah yeah time flies when you're having fun we're about to be in the fourth quarter of the year. Well, anyways, good luck to everybody who's looking for work we'll have that job thread tomorrow. And then. On Thursday we'll come back. And, you know, I thought this stream I would finish Origin. It feels like we've seen most of the functionality now. Stories by Origin. Domain. I almost wonder if

03:51:14nogweii found some hairy bugs in the process :D
Yeah, domains, their page of slash domains slash github.com, that's going to become a lot less discoverable as all of the stories link to the origin page instead of the domain page. But I guess that's only the case for the couple of places we use origins. Yeah. Oh, we certainly did find some hairy bugs in the process. This thing has been all corner cases, I swear. Aside from frustrating bugs with migrations and the order of operations and naming the form fields, it just has been a couple hours of corner cases. All right. Oh, let's bring this to do over to the scratch.

03:52:17Because that one's going to want to test. I don't think I have any other. I might have one more to do. Really? That was the only one? I thought there was one in the controller. Maybe I already cleaned that up. I'm just trying to wrangle up the to-dos while they're very fresh. This diff is getting pretty big.

...48nogweii what diff pager is this, btw?
okay i guess there aren't but the last thing to do is think about are they're called feature tests now feature test for new domain feature test for editing a domain replacement Is it the selector? These... If I fought routing and params so much, I would like a couple of outside-in smoke tests. Just one. It's not a huge priority for this low usage kind of thing, but there's just so much happening on the page now. And they'll be fairly easy to knock out. And then what other kind of tests? The model has a couple for these. Yeah.

03:54:27And then the main model. Hang on. Existing stories origin ID. Yeah, that's what I'm saying. That's a spec, because that's a fairly thing. What diff pager is it? The diff pager is diff-tastic. nogweii ah!
pushcx https://github.com/Wilfred/diff…
Yeah, it's... Here we are, a structural diff that understands syntax. I like it quite a bit. I have to have a wide terminal for it, but that side-by-side view just so naturally matches the way I think about diffs. I started out looking at diffs, and it was always the plain patch view of minus, minus, minus, plus, plus. And I can build it in my head, but the first time I saw a side-by-side diff, I fell in love. So I'll throw this in the scratch too. Will I? Or will I just fight my clipboard some more?

03:56:03There, yeah. I don't mean to imply that I'm the author of DiffTastic. Maybe I'm overthinking that one. I really like the DiffTastic. It says it understands syntax, and it does. It's smart about capturing one semantic block of it to end, as opposed to... sometimes with the line oriented diffs if i had inserted something in the middle you know you would see that changes everything up to the end and then it leaves the end in place and it's just clunky because you can work out what you're seeing after you've seen it a few times but like here sometimes it would say you kept this end the same and then you inserted these lines before and this end is the same, DiffTastic handles this kind of repetitive structure better. And that side-by-side plus less noise in the diffs is just so lovely. I want to say it has syntax highlighting that I turned off, because who uses syntax highlighting? I get so little out of syntax highlighting besides, is there a run-on string or a run-on block All right. So then hopefully next time we'll bring home Origin. If there aren't any more questions, I'm going to roll out. Thank you all for hanging in there. And I will see you again Thursday morning. nogweii bye!
bluwumeaway cya
And we will try and get Origin over the line in all of its UI glory. All right. Take care, folks. Bye.