That's inconvenient, I want to do something awful
Streamed
Comment editing/previewing is stable, an idea for upvoting, fixing unhiding by deleting js, and more story merging.
scratch
topcis
PRs, issues
self-promo rule https://github.com/lobsters/lobsters/pull/1498
emoji https://github.com/lobsters/lobsters/issues/1497
sitemaps https://github.com/lobsters/lobsters/issues/1496
bump nokogiri
story merging
fixed up singledetail
error(?) in brakeman https://github.com/presidentbeef/brakeman/issues/1927
font size experiment https://github.com/lobsters/lobsters/issues/1284#issuecomment-2749425161
title
the more code I delete, the fewer bugs I have
post-stream
Transcripts are generated with whisperx, so they mistranscribe basically every username and technical term. They're OK but not great, advice appreciated.
Recording
30It's Thursday. This is the Lobster's Office Hours stream. I'm Peter. This is Lobster's.
...43So for Office Hours, if you have any questions about the site or the codebase, you can pop up and ask questions at any time here. And then otherwise I work on the site and the codebase. So I'm just kind of getting my morning started. These Thursday streams are harder on me because I have to wake up. And I thought they would be easier for the European folks, but they just seem to be quieter. And I'm not sure if it's that... It's because I'm just not able to do the run-up tweets on social media, but I get a lot fewer viewers on Thursdays. So, I don't know. If you're in the EU, it would be nice to know if you'd like this to continue. Otherwise, I'm kind of noodling off-screen here where there's a couple of threads on the homepage. Wanted a little bit of mod attention.
02:14The healthy IG thing is eh. It's not much about making software. It's mostly about, hey, look at my project. which is okay in moderation.
...43I always check in on these stories that have some text on them, because it's real common that people use the story text for stuff that it's ideally not for. There's not a lot of structuring I can do, People look at forms in a very, what's it called? A very functional way where it's like, I want to do something. What are the affordances of this form? Trying to explain something and using UI jargon is not super helpful. So affordances like, what can you do with this? And so like a checkbox, you can check it or not. So people kind of skim those. then a text box obviously you type in a text box and so they just default to typing in the text box and we try and be smart about displaying some context sensitive help like the first time you submit a story you see the story guidelines but those disappear kind of naively so if it's been a while since you've submitted a story you don't see the story guidelines so those are more likely to get mistakes and the Let's see the other part of it. The title has inline text that gives help. And that one works a lot better because it can be context sensitive. And it animates. So if you paste in a title that includes something that is probably a separator that includes a site name. So I don't know anything about this article. But if it said, you know, A little animated thing opens up and says, hey, we don't include site name in titles. And since I added that JavaScript, that has largely stopped happening.
04:48All right. So let's take a look. So what is there to talk about? The topics for this one are the usual PR and issue review. and the recent meth thread on self promo, which we've talked about on stream a few times.
05:09I know it's all set up here. So let's go to GitHub. Oh, yeah.
...29pushcx Drop an office hours question in chat any time!
I'll leave a little message in the chat, because I think on Twitch, when you pull up the stream, it does show folks that scroll back, so people have a little context, or at least understand the whole stuff, of course, because lots of people drop in and have no idea what the stream is about.
So let's see, where was I?
I think there's a little activity on this one around OTP codes.
I know there was some activity around the issue for,
the account takeover.
07:00OK, so just one small style comment, kind of question. All right, so not much there. Yeah, so the password issue.
...37Well, that's pretty great, actually. So this is exactly the kind of voice of experience and expertise that I had hoped for. So there was a recent thread here.
08:13pushcx https://lobste.rs/s/tzjxrc/pass…
Where did it go?
Yeah.
So this thread on password reuse, I happened to see it just as it was posted.
And oh, hey, top comment is from DPK, who is a stream regular.
If you are here, good morning.
...44chamlis_ hiya! audio is stuttering I'm afraid :(
I have worked with companies, this is an interesting topic, of Cloudflare appears to have got this data by spying on clear text usernames and passwords passed through their infrastructure between web service, user browser, and their client servers, and analyzing the data they got from that spying.
That's an entirely plausible way for them to get this data.
Oh, shit.
Sorry about that.
Thank you, Shamless.
I really have to spend more time doing that volume fix, clearly.
Or automating that volume fix, because like the...
footer on the top of the or at the bottom of the page that the stream is live that's a manual process and on monday i forgot to turn off the manual footer and it was on i don't know for like 12 hours after the stream ended before i came back to my computer and somebody actually a couple of somebodies had told me that it
is still on, that was embarrassing.
And very counterproductive for actually using it.
chamlis_ yep it's good
So anyway, Shameless, if the audio should be good now because the workaround is in place.
But what I was saying here was I was reading Daphne's comment that Cloudflare may have kind of done a man in the middle attack to get this data.
And I don't know if this is how they did or if they've said anything about it.
I've seen a few people make that point on.
Yeah, no, I'm kind of skimming for a edited to add or let's rebut.
I know a couple of companies and I've worked at a couple of companies that have really interesting data sets.
So just to pick one I didn't work at and have no special knowledge of, you can imagine a company like Uber has really interesting info available from all of their driver phones where they know all kinds of things about commute times and where there tends to be traffic and
especially the movements of people in a city who are more well-off, because that's going to be their user base, right?
If you're poor, you don't get to take taxis as much.
And so they do have all kinds of interesting data there.
And they could do an annual, like there's that Spotify wrapped that tells you all the neat songs you listen to.
Uber could do a like Uber wrapped that's like
you took a walk of shame taxi three times and that would be like a saturday or a sunday morning taxi after taking a taxi to the club the night before right like they could do all that kind of stuff but they don't because they don't want people to think about how much invasive data they could have and all the stuff that they could do with it so i was very surprised having worked at folks that
genuinely have really interesting data sets that don't talk about it because it's so potentially sensitive and they don't want to be associated with having that kind of intimate look at things, I was really surprised that Cloudflare did this analysis.
So I'm super curious to see if Cloudflare comes back and says,
Oh no, we got the data here from something else.
13:15So where I was going with this before I rabbit-holed into DPK's comment thread was I saw this a couple of minutes after it was posted and I put on the sysop hat and I posted a comment that said, hey, we have an open feature request about these kinds of password issues.
...41I would love to hear experienced voices. And, So I am really actually super pleased that this comment led to getting exactly the kind of very experienced response and criticism that I was hoping for.
14:08Anything else here?
...21This one is definitely a response to DPK, but they kind of... They must have missed and got the wrong comment form.
...37Alright, so...
15:32gsora_ hello chat!
Comment.
I think I can just cross these things out.
So if I cross these things out.
17:21Let's say this properly.
...51Let's see here. That was low default timeout. What is there? Low default timeout.
18:31Let's say FAC.
...40Their timeout is 1500 milliseconds. That is a lot higher than I expected. I was thinking 500 milliseconds to be generous.
...55All right.
19:56They put it.
20:13by Royce Williams. Is this just a static list? That's... Let's wait. Is this v6 or v2? Why would I want the older version?
...52This is kind of an odd way to maintain a project. And it's Three years out of date?
21:31I'm aware that, yeah, people are just reusing common passwords and that this is not going to change much on a year-to-year basis, so it's probably fine.
but i don't know i assume at some point somewhere in here there's gonna be some kind of pop culture reference bratz there we go so bratz is a at least in america that is a doll
gsora_ bratz! passion for fashion
popular doll change that's like a kid's password abercrombie i just saw go by that's a clothing brand brad's passion for fashion i mean password fashion so i mean if it really is like five out of twenty thousand of these are fashion based at least that i can recognize in english
22:41I think that's a brand of cookies.
Might also be a style of cookies.
Mary Rose.
chamlis_ I hope "love", "sex", "secret", and "God" are in there
Sounds like that's either a famous person I don't know or a brand.
23:03Oh, are you... Let's take a look.
So...
Shamless here is making a great reference.
So we got love.
We got I love you.
There we go.
Coming in at 100.
Well, there's like 20 lines of comment up there.
So up there around number 100 is 126 is love.
We have sex, sexy, sexy 12.
There we go.
So if we're taking off about 20 or 30, that is number 1300.
Secret.
Coming in about $175.
And God.
God is good.
Oh wait, I didn't know if that reset the cursor.
I love God.
Godzilla.
God is love.
Here we go.
chamlis_ fantastic
Here's just God coming in around $2,900-ish.
Ah, man, if you can't get your movie, your facts about passwords from 30 year old movies.
24:16pushcx https://en.wikipedia.org/wiki/H…
So I genuinely think one thing that might have happened is that the implementation.
So there is a famous bit in this movie that the most common passwords are,
like secret sex and God.
It gets a callback or two.
I think part of it is the reason it's not is enough sites have created like your password can't be a dictionary rule or your password has to include a number.
Those kinds of like basic attempts at sanitization that
That's why those passwords are far enough down is because you can't actually use secret as a password everywhere anymore.
But these rules are not good because you see like password one way up here.
And that's a we wanted to use password.
But the rule said we had to include a number.
So we used password one.
surprised i don't see password zero here on the first page password zero one and password zero all right so it's in there it's just not as high as i would have guessed that's the value of data right i'm sure they'll remake the movie hackers and they can come here to this list and then they can have you know
Angelina Jolie, give a smoldering look when she says that the most common password is 123456.
This film really is campy and fun.
I can't recommend it enough.
Although, if you want to watch movies about hacking, the best movie about hacking is...
pushcx https://en.wikipedia.org/wiki/S…
Sneakers.
Whoa, wrong Wikipedia page.
Here we go.
Also from the same era.
A weirdly excellent cast.
Like, I have no idea how they got such a great cast.
But... Lovely film.
It's kind of a...
Sneakers is fun in a way that movies...
often aren't anymore they either go for very silly as opposed to just a little bit campy and not taking itself too seriously and you know they fret about things but the stakes are actually pretty low i don't know i am sure there is a better film critic version of this than i can give off the top of my head but
27:28Actually, why not check the local password list? first.
29:35Thank you.
30:38That's about it.
31:15pushcx https://github.com/lobsters/lob…
Hey, look, I even got the mark down right to cross things off.
Good.
pushcx https://github.com/lobsters/lob…
Well, you know, I shared links to silly hacker movies, but I didn't share the link to the bug I was looking at.
All right, so this one, just working up the list about editing a comment.
Boy, we had kind of a cascade of issues.
And everything has been cool since we worked through shameless is PR.
Oh, this is your first PR and then you had your second one yeah and since we worked through her PR we figured out what was going on okay so.
32:22I'm going to grab this. See, there's the Git cross-referencing thing where I always feel with GitHub like I'm doing a lot to try and make sure there are cross-references.
...47I don't need to explain why I'm closing. Everybody knows you close when you don't think it's open anymore.
33:29Get that squared away. Oh, what? I haven't been updating my... Clicked over. I haven't been updating my Scratch. Showed an old browser for a second there. All right, so that was...
34:00Where was that? Was number 1478. There we go.
...20What else did we hit? We are going to look at
...29Rory O'Kane's something about feedback I haven't seen these yet so I know Rory you drop in sometimes if you're here please say hi but let's take a look what are we looking for yeah this is correct we do oh light and dark
35:05oh yeah that's super irritating that's fair so that's so i'm actually in a sunny room and i can't see the difference in these light colors hmm
...46gsora_ woof, different status color for a pending upvote and confirmed upvote sounds like hell to implement
gsora_ server-side i mean
princessxen hey nerd
Well, server side, it's fine.
Because it never touches the server.
princessxen yep
So from the server's perspective, either there is... Oh, hey.
That's Z, right?
Are you going to stream after me?
princessxen i have to work today lol
Can I raid you?
I'm learning all the Twitch terms.
Are you dropping in because IRC is on fire?
princessxen my anti scraper software is taking off too
Ah, work is the worst.
Man, I recommend against it.
Anyways, thanks for dropping in.
princessxen yes
So from the server's perspective, either there is or isn't a... Oh, did you write Anubis?
gsora_ much love for anubis
Or what's the other one that folks are adopting with the anime girl?
princessxen anubis is the one with the anime girl
Yeah, I saw that...
gsora_ a worthy use for PoW at last
I didn't realize you wrote that.
I knew you were...
Okay, Anubis is the one with the anime girl.
Cool.
princessxen nepenthes
There's another one that's getting mentioned a lot the last week, and I don't remember its name, but... Yeah, I saw that one.
I was reading the article that was about various projects that are starting to adopt it.
Dependthes, yes.
You're way ahead of me.
princessxen anubis is rageware that i wrote while vibing to inhuman mashups lol
That's the other one I was thinking of.
Sorry.
With the whole, like, keeping up the stream of pattern, it's really hard for me to change gear and think of specific nouns.
37:25Ragewear is an excellent term for that. Hmm. I think that's kind of my rake replacement, is maybe ragewear, because I got really frustrated trying to implement parallel tasks in rake, and I'm really frustrated at Rake's overuse of Ruby syntax where I cannot memorize all of the clever things it does with syntax. Anyway.
38:04I just left a comment about that whole situation.
where are we finding my own comments i don't know if it's useful but i i have seen a lot of badly written scrapers hit lobsters and i think it's because we have a lot of like junior programmers and when you are writing your first bot of oh i could make a thing that's crawled a website what websites do i know and then they think of a site they visit every day which might be lobsters
And so I don't know if I'm actually seeing a higher proportion of bots or I'm just guessing it, but it feels like we see more than usual.
princessxen it's mostly AI companies using finite numbers of headless chrome instances
And I have the impression that a lot of the AI crawlers are just immature because search engine crawlers used to be bad in very much the same ways.
princessxen but
Yeah.
39:15princessxen it's finite numbers of headless chrome instances
princessxen remember slowloris? :)
I'm very, yeah, it's finite numbers.
And there were some really interesting comments here.
And yes, I do remember slow Loris.
princessxen thinking about doing it backwards
pushcx https://lobste.rs/s/dmuad3/miti…
princessxen from the server to the client :D
In the, this article that I just merged in this morning has some, let's throw this link in the chat.
We're going to talk about it.
...44Think about doing it backwards.
Yeah.
I mean, if my point is that they are probably just immature, yeah, doing it from the server to the client, as long as you don't exhaust the server, you really want
princessxen yep that's why it's a reverse proxy server
make it some kind of middleware like lots of people use nginx or caddy in a reverse proxy mode like we use nginx to talk to puma the rails web worker you almost want to add another proxy layer in between so that you don't exhaust because the thing with nginx and caddy is
They start out as very thin reverse proxies.
princessxen also working on making it a caddy module, and maybe grafting it into nginx?
And then as they gain features, they become moderately heavy reverse proxies.
And so then as soon as you want to add something, you want to add it as another layer so it can be really thin and cheap.
I don't know.
It's kind of funny that there's that lifecycle to them.
Yeah, I know it's possible to make Nginx modules because I've loaded some.
princessxen idk, probably not worth it lol
So I'm certain you could just make it a module for those things.
40:57chamlis_ I think the jargon for that is "tarpit", endlessh is the one I've seen
princessxen endlessh is great
Anyway, the whole thing is tar pit.
princessxen it's the one that has an infinite ssh banner
Interesting.
I haven't heard of that one.
gsora_ love for endlessh
Endlish?
Is it endless SSH, basically?
41:24Oh, that's clever.
Yeah, and I should put this on prod because every time I look at the prod logs, there's just endless people knocking on SSH.
gsora_ there's also a ruby script that lists the top offenders and their session length
And I've been tempted to move our SSH on to I'm saying, I've been tempted to move the lobsters prod SSH on to my tailscale network, because I use it for home computers.
But
princessxen i'd suggest moving it to a wireguard setup and having a backup wireguard setup too
I have done just enough, oh shit, Lobster's prod is broken from random other devices that I'm a little reluctant to do it.
42:13chamlis_ I don't get too many failed logins just moving it to a non-standard port
Yeah, Z, the problem with moving it onto WireGuard is
I don't always have...
chamlis_ heavens knows why they even bother slamming their heads against pubkey auth
I mean, I have debugged Lobster's Prod issues from my phone.
I have debugged Lobster's Prod issues from other people's laptops because I don't always have...
I don't know.
I've only been using Tailscale for eight months, ten months, something in that neighborhood.
So I'm still learning to trust it.
And it's been utterly reliable, but...
gsora_ bots are dumb
princessxen yep
if I'm very fundamentally locking devices out of the ability to fix things, like that is the benefit, but I have to have a lot of trust in the tool that's doing the locking.
I don't know.
princessxen it's a terrible situation lol
Shamless, I would suppose that the answer to why they hit pubkey auth is the same as
I've closed the tab, but have I been pwned is lots of machines have been popped, and so they probably have lots of private keys.
43:30gsora_ we should build a new internet
Yeah, so my guess on this story, and I admit this is just a guess, is that in the same way search engine crawlers
matured to the point where it was worth worrying about efficiency spend, the AI crawlers are likely to do the same.
Because they may have infinite VC dollars right now, but that runs out.
And at that point, you're like, boy, what if I took 90% off of our crawling bill?
Oh, I would get a promotion.
princessxen the point is to waste their money :)
And then they stopped doing some of this stupid shit.
Maybe I'm just hoping.
44:19Yeah. Oh, yeah. I mean, Anubis and Nepenthes are forcing them into maturity in the same way that they are forcing sites into maturity around caching and other things.
...46Do you know anybody at Cloudflare? Maybe you could get them to adopt Anubis. And then when all the AI crawlers light on fire at once because half of the web is behind it. There you go. I don't know.
45:17princessxen i'd only accept a buyout from cloudflare if it means eastdakota resigns and publicly states that trans rights are human rights
So jump in... You'd only accept a... Oh, I wasn't suggesting that...
princessxen CTO
I don't know who that is, but I get the impression they're a prick.
princessxen very libertarian
Is East Dakota the CEO or something?
Hmm.
Well, scratch a libertarian.
And you know what you get.
...54chamlis_ a bill?
chamlis_ :)
Yeah, I was looking at it.
There was a story that went by.
I just saw the headline where...
It's falling off.
I've thought about...
46:17So I went to Madison Ruby last, what, fall?
Was that in August?
And it's run by, mostly by a married couple, Jim Resnick and his wife, whose name I am really forgetting because Jim does all the PR.
Oh, shit.
Yeah, I'm, I'm just blanking on her name.
But Madison Ruby, it is really clear from talking to them and from attending, they put it on because they love Madison and they love the Ruby community.
And I reviewed talks for it.
And not so secretly, Jim was trying to get me involved because he was like, if you see behind the curtain, you will realize all the steps that are involved in putting on an event.
And maybe you will put on an event, which I think is mostly,
he chooses to recruit people to there's some amount of hey will anyone help me whitewash this fence that i do trying to get contributors to the lobsters repo but there is also he wants people to realize that it is pretty straightforward to put on a conference so it had me thinking the last couple of months around a lobsters con but the
While I try and stay out of politics, the US State Department's prohibiting trans people from visiting the States is just dumb, evil bullshit and makes it impossible to put on a conference in the United States.
And I had hoped if I was actually going to start a Lobster's Con, like, at least I could start it in Chicago.
princessxen there's always Ottawa :)
Because we're a pretty good city for getting to, really well connected on flights.
chamlis_ can't say I'd recommend the UK that much on that front
But if I have to go and start it in Toronto or Vancouver for visa issues, it's just so much harder to actually run a conference that I probably will not start a lobsters conference.
All right.
Yeah, I'm not super interested in visiting the UK, but that's for different reasons.
49:27gsora_ EU needs some conference love :^)
Yeah, I have no idea what it would take to put on a conference in the EU.
As a would be first time organizer.
There's so much stuff to learn and do that.
Adding the also it would be international travel for me makes it a hell of a lot harder.
And then
I previously worked in Canada and had a work visa and
time I visit I get questioned about are you here to work and I understand the point of that question because like if someone previously worked in the country maybe they are coming back to work again that's a totally legit question and I you know show them no I have a tourist itinerary here's the hotel I'm staying at here's you know the thing I plan to be a tourist at and it's cool but
Hey, I'm here to put on a conference is kind of work shaped or business shaped.
And I think that would actually be super hard for me personally.
51:34gsora_ i used to organize a small linux day at my uni (~50 attendants), it was hell, i can't imagine organizing how difficult it would be to plan and execute lobstercon
What's the right term for people who can't see colors very well?
Like the red-green colorblindness?
52:46gsora_ daltonic?
We're not being silly about this.
53:30Daltonic?
You used to organize a small Linux day and it was hell.
Yeah, in college I organized LAN parties because I'm old enough that we were still doing LAN parties.
pushcx https://bookshop.org/p/books/la…
Actually, speaking of, as long as I go into books here on stream occasionally, there is a coffee table book by, I follow her on
gsora_ the flash-overexposed pics of people playing computer games are a vibe
think blue sky now there is a coffee table book on land parties and if you are of a certain age oh man this is this book is just a nostalgia bomb like there isn't any kind of click inside are there more images somewhere i'm trying to find her
site because i know there are a bunch of images on her site yeah like this this could have been me and my buddies in high school like this is obviously a bunch of yeah the flash overexposed pictures oh my god if you were there this whole book is a nostalgia bomb
Like, any of these could be pictures of me.
I know I don't stream with a camera, but you could just throw a dart at this book and I look like that.
Or I did look like that in the, you know, 80s and 90s.
Now I look, you know, the same, but older.
This book is... God, this book is so great.
I love it.
55:17The other...
I can ramble.
The other what's the proper title of it?
pushcx https://shifthappens.site/
The other excellent shift happens.
The other excellent book to read is shift happens.
And I say read but it is this giant tome.
Oh, what a fancy intro of
This guy had a famous I think it's come up on stream before this guy had a famous Twitter thread where he ran into a typewriter museum and he was super interested in it.
And then he just totally went down the rabbit hole on the history of computer keyboards.
gsora_ oooh yeah shift happens is amazing
And it's this wonderful three volume set of books about
gsora_ on a similar note, i got a copy of https://opencircuitsbook.com/ when it dropped, truly amazing
the development of the keyboard that we know today and it is clear reading it that he just loves the topic to death and on almost every page there is a paragraph that is like look this isn't super related but i ran into this and it's so cool i have to show you or tell you about it and i appreciate that level of enthusiasm and just having fun with the topic so
Anyways, if your coffee table is bare, get those open circuit books.
I haven't heard of this.
Is it like doing MRIs of?
Oh, this is right up my alley.
57:07These are lovely, how did they get these colors are they. false color.
...21gsora_ the photography work is on another level
Some really nice macro photography here and then what did they like.
gsora_ yes! it's all cut in half physically
cut these in half, I guess, because you can kind of see it roughly playing here and then they must have polished it wow.
That's funny.
It's like, that's what it looks like in my head.
Yeah.
And then they clearly like capped a bunch of processors.
Outtake images.
Yeah.
There must be a ton of those.
I can't even imagine.
What a ton of work.
That's really fun.
Thank you.
I'm going to, hold on.
I'm going to yank that over to a personal browser so that I can buy this book.
That's lovely.
Thank you.
That is exactly my jam of check out these neat things.
58:26So, Jisor, did you still have a question about this?
gsora_ more than a question, a general comment
You had said something about the server side before we rabbit-holed into scrapers.
gsora_ ah yes, the client side must react through JS
server side it's fine because it's a a boolean operation where the server either renders the not upvoted or add the css class that it's voted it's the client side that changes where we add a class we animate to it and then instead of just doing a fire and forget on the upvote which is what the front end does now
gsora_ sounds like htmx
it would animate out the class to this finished state.
Yeah, yeah, so it's all on, it's just the JS side.
Right now, I want the JS.
Yeah, so it calls the vote comment function, and this does,
So we remove the class uploaded we remove the class flagged there's we do this optimistic updating the score.
gsora_ oof, spam ^
and Then, at the end it fires this off, so the tweak would just be to.
Let me ban this bot real quick.
But the tweak would just be to, yeah, I got them.
There's like a multi-step report process where, what is it?
01:00:22Oh, here we go. There are like three different expandable menus in the username thing. And then I have to click through five things just to report spam. And then I have to block. Twitch could make that easy. And then he's not actually blocked. Come on.
...54if I could fix Twitch's UI.
01:01:01So yeah, it would just be a tweak to this function here, where instead of animating to the status of upvoted, you animate to pending upvoted. And then over here, when you get the server 200, Honestly, the hard part on the CSS is you would have to rebuild this triangle. So what else do we have? We have a bug. Oh, I think this was reported to me on IRC.
...59I'm not sure I follow what this bug is. One works properly, the other does not. Are they saying they actually see the word unhide twice?
01:02:28gsora_ wow TIL the upvote button is all CSS
Let me fire up my local Rails server.
And then that'll come up in a second.
And I assume I have a couple of stories hidden.
They're almost unreadable.
Yeah, so I only see one unhide.
But if I click through to the story, I still only see one unhide link.
I'm not sure I follow this report.
After logged in.
On the story page, the menu line just below the title starting with authored by has a hide on hide option.
It doesn't work.
Another line appears below.
It's only visible after refreshing the hidden page.
So I think they're on the single story view.
It starts with you have
Oh, this is the new thing I added.
You have hidden links to this story.
So that goes to the help text.
Yes.
You can unhide it.
Okay, so it's the new thing I've added that's bugged.
So this one is correctly Ajaxing, and then this one that should work.
All right, so there's the bug.
01:04:05It should be going to story unhide path. And it's possible that won't... Yeah, so it's doing a get instead of a post. That's what's happening. All right. So this is the... This is just basic CSRF protection. We have the logout link that does this. So where's that code? We want to do a link post and then...
...53So this wants to be...
...59It's going to post to the story on hide path to make it visible again. It does not need a confirm. And I think that might do it.
01:05:16What painful CSS. Why is this?
...26Why is this indenting? Because the form is a block element? Oh, no. It says display inline. Where am I getting a block from? Your display is inline block. That's fine. Why is there a p tag here?
01:06:03Hold on. So one thing that I feel like I might be getting tripped up by. Yep. Yeah, and it has been forever. So this view where it is rationalized, oh, I get it. If I have a p tag, the form tag is considered a block level element. And so the browser is inserting a close the inline element tag. And then that other slash P is inserting a, okay. So honestly, if I just take the P tag out of this, then I'm nesting a block in a block. And I think I can just have inline text. It's the, yeah, there we go.
01:07:04So now if I click unhide Not the great response I wanted. I'll have to update the controller there, but that's fine.
...22So instead of rendering, we'll say, I feel like I was just breaking something with calling request.xhr.
...42Yeah, so I called request.xhr. Did somebody comment on it or suggest an alternate path? All right. I'm just going to do it again.
01:08:10Ooh, all right, what do I do? All right, get this up here. So if I reload this, it should be unhidden because that 200, yep. So if I hit hide now, it changes. And if I reload, I get the view of it. And now if I click on hide, it'll just do a pull page refresh, which is just fine by me. Great. So then I'm going to, Copy this logic up here because it is the same thing for hiding where we don't need to add a flash or anything. All right. So this should fix the bug. Let's run the specs. Look at me being responsible and remembering to not break the build. Who does that?
01:09:31What was that? Issue number 1495.
...42We can just delete that comment. Did I put this in the scratch?
01:10:10That started deploying. And the bug is closed, great.
...50Alright, nice to just look at a bug and immediately whack the bug. Because as fast as I saw it, I was like, Oh, I know what I did. We've seen this kind of thing before. Alright, and I believe that is all the stuff that's changed since I last streamed and went through everything. Yep. Great. Great.
01:11:20This is one of my pet peeves with object orientation, actually.
...33I gave a whole talk that came down to what a pain this is, especially in the active record pattern.
...50Yeah, this is a thing I have. What a great article.
01:12:10Well, all right, it's much easier said than done.
So many libraries force you into having half constructed objects
Like I've tried to do this with the active record library in Rails where I've said, oh, you can't have attributes or you can't have, you can't have, so if you have a typed attribute, like a URL on a story, we have a bunch of validation rules around a URL.
And so I said, okay, well, I'll make a URL object that can only be valid.
And so you either get back, not that this is a monad, but this is a monad.
chamlis_ doing dependent-type proof stuff really makes me like thinking of types as "there is a proof this variable satisfies a bunch of conditions"
Either you get back a valid object
Story object or you get a list of errors of things that we consider wrong with your URL and there is absolutely no way to adapt this to the active record library, because the active record library is like no you just put garbage on your models and then every method, you have has to know that your attributes may be garbage.
It was a very frustrating attempt.
01:13:24pushcx https://lobste.rs/s/z4halj/half…
What a great article.
So let's grab that link and share it.
And then I'm putting it in my personal browser off screen, literally just so that I can upvote it because I like that so much.
All right.
Where is my... No.
I am going to step away for a second and then we can talk about the... Oh, that is in a terrible place.
What if I... Can I scroll to a place that's visible?
No.
All right.
I'm going to run for a second.
I'll be right back.
And then we can talk about that meta thread or anything else folks have questions about.
01:16:10Alright i'm back look at me remembering to turn off the note so shameless you don't have to remind me.
...25yeah i'm gonna have to. come back to that article. and leave a comment about what I basically just said, because.
...43I'm not seeing anyone who has made the point that there's interacting with other libraries that... Also, this is not PLT. Actually, this is just programming.
01:17:09Did they mention specific languages? They give examples? Didn't think so. Well, there's go.
...23See, but they don't really give any samples.
...44Yeah.
...50OK, big boy, you don't need to lay on the mouse because if you lay on the mouse, you get huffy that I am touching your butt. There you go. Got to shove the cat around. So. So let's look at the. That's done. That's done. That's all the PR and issues. There was the recent meta thread. If anybody wants to talk through that.
01:18:36pushcx https://lobste.rs/s/gqyrxk
Let's throw this in the chat.
So if anybody had opinions they wanted to share or talk through, this was pretty active.
01:19:26This comment from fa and F, who I think has dropped in stream say hi if you're here, please was really useful because this kind of let's look at the actual numbers is. very useful for making sure we're not over pattern matching.
01:20:14gsora_ i understand where the author is coming from, but i'm not sure if it's guideline-worthy
gsora_ i usually collapse those threads and move on
Yeah.
01:21:12If there's no questions i'll just kind of jump on move on, because I don't have too much i'm ready to say about this. there's a lot of thoughtful stuff here, though.
...27talked a few times on the thread about or on the stream about self promo so there's some stuff in the stream archives about it and then otherwise. This one is probably better handled by improving the self promo guideline and features, especially for making them less naive. A big chunk of them are the new user period is just a strict, not a strict, but just a, what are you in your first 70 days as a user? And a lot of folks create accounts. And then a couple of years later, they get really involved in something. they want to promote it whether that is a project they're volunteering for or a startup they've joined and then we see the bad behavior and i think the better way to fix it would be to recognize the root cause rather than the symptom of folks chiding which is also not super great but I think is not the root cause here. So I was gonna jump back into story merging. Let's see, where's my time? An hour 22, all right. So usually I go for about three hours. So I'm gonna work on story merging for a minute, which is also a meta topic. And I am not, if you are watching this in the archive, I'm just trying to use office hours well. I am not ignoring the big meta thread about self-promo. It is on a lot of these, unless I feel like something is a bad misconception where it seriously misunderstands something about the site or the community norms, I try and have a pretty light touch on a meta thread because otherwise. I stopped all over it. If I post my opinion first, then it becomes, do you agree with the admin or not? And I would rather see more opinions and more experimentation by being quiet myself in the thread for a couple of days. And then I'll come in. Maybe later today and tomorrow and kind of post a well, let me round up where we got in this thread. The discussion is just much healthier if I don't step on it. And I do think that's generally a really good thread we have going now actually.
01:24:38YmeYnot45 extraYep extraYep extraYep
ah hey why me why not welcome back extra yep so is that just a way of saying yes yes yes to my idea of not accidentally stepping on meta threads as this is up or does it have a different twitch meaning than i know because a lot of this stuff just i never know what the twitch emojis mean because i don't watch a heck of a lot of streams
I do watch Zs.
So for folks who've been here since the start of the stream.
YmeYnot45 Yes, and it is the extra credits (youtube) cat. Which Hurray for Cats.
Princess Zen streams on, what is it?
Friday, the middle of the day for me.
I watch those.
I don't know.
I would say about half of the weeks.
I at least have it on in the background.
The Extra Credits YouTube Cat.
Oh, Extra Credits is that
YmeYnot45 Yes
That series about video game design, right?
All right.
Hooray for cats.
Good deal.
01:25:47Is this a... Merge story, and that's why it's... I'm looking for a merge story. All right, good. That's why it's high in my history. All right.
01:26:08Yeah, so where I got was working on the cabinet and getting that working. So let's just go ahead and add some merged stories to this page so that I can work through these together. Yeah.
...41And then everything is tied together with global variables, because this is Rails.
So we'll see if I can actually get these onto the page.
pushcx https://railsconf.org/
Oh, speaking of Rails, the last RailsConf will be happening in a few months in Philly.
YmeYnot45 Last?
I think they have early bird tickets I don't know if they sold out or what probably the conference itself will sell out, but this is the last one of these because.
yeah.
01:27:35I'm trying to decide how spicy to be in explaining this.
pushcx https://rubycentral.org/
The short version is that the conference that is run by, so Ruby Central is the, yeah, the nonprofit that runs support for the Ruby language and ecosystem.
And they have run RubyConf and RailsConf for...
I mean, Ruby for...
I want to say RubyConf has been going since 2002 or 2003, something like that.
And RailsConf has been going since 2006 or 2007, something like that.
And...
dhh who is the guy that runs rails decided that he wanted to run an official rails conference and so he took that over so if you want you can go to the dhh show instead this oh this is exactly the one i wanted to add and this is not the single story view so that's bugged
01:29:04So let's fix the bug.
...14Let's find a bug.
...25OK, so you know it's true, but you didn't do it. That's weird.
...46Did this go to false?
...53True, true, true. OK. Kind of climbing up the. Ifs. So this is happening. Single story getting reset.
01:30:16So these are for single story view. True. False. False. True. Okay. Why am I not seeing all this extra stuff. So if I say echo, yep. Oh, is it because this is coupled to the database? So we got true and then yep, it's going inside, but then it's failing because it goes and queries these out of the database and yeah. These are not stored, are they?
01:31:11Hold on. Right, that's where I got to was if I store these in the database, I can't display the cabinet in production, which I would really like to do. But in Rails, everything is global variables and everything is coupled to the database, which is the ultimate global variable because it persists between requests. It is the big global variable in the sky.
01:32:00chamlis_ in the cloud
And what's worse is the view doesn't directly use this scope because it has to preload stuff.
...19Very true, Shamless.
Shamless.
I'm learning to pronounce it correctly.
It's going to take me a second to sort out my brain, but thank you for explaining again.
All right.
chamlis_ it's not my real name I don't really mind
So then the question with this scope is who uses the merged stories scope and doesn't want this behavior?
...54Yeah.
01:33:04List detail. The search. Actually, everybody is. Oh, so this is repeated from list detail. So this is the heinous inline partial happening. That's fine. The stories controller touches it. And I recognize this as part of the score function. let's look at the stories controller because that probably should be using it where i'm headed with this is thinking that maybe if i move not delete it in and i can move this for presentation into its own scope which it should be or reuse the existing for presentation scope Then I can stub this in the cabinet because what else are you going to do, right? So this is we load the user votes.
01:34:15Yeah, not deleted is fine. And actually, why is this using not deleted nil? Shouldn't it use the current user? Yeah, it probably should. All right, so what else used it? The story math, yeah, and the voting should ignore deleted stories.
...48So I'm going to have to make merge stories take an optional user because the authorization is getting shoved down to the model level again, but That's real, so I have model story. Merge stories is not a scope. It's a collection, and so I can't add an argument to it. I have to rename it. All right, where's that for presentation?
01:35:32That is correct.
01:36:13Tags for hidden by, not hidden by, saved by. Yeah. All right. So if I say, let's put down here the scope is What am I going to call it? Because it's not... I want to call it Merge Stories, but that's the name of the collection. So I'll call it something. And that's going to say... See, what I really want is to add a scope to the Merge Stories collection. But I can't do that. I don't think this could be a... Maybe it can be a scope. We'll see. So if I say for presentation for this user, no, for presentation and then not needed the user, which means I'm taking the user optionally. Well, let's make it optional. Let's make it mandatory. Force people to be explicit.
01:37:58I guess that's roughly it. So then if I said this, what's my error?
01:38:25Right, it's not an instance. It's not a scope where I'm saying, story, give me all the merge stories for this key. It needs to be a method that is just going to shove the issue up a layer. Let's take a look. Let's find a good place to put this.
01:39:06lost my little tag browser didn't i oh there it goes all right yeah not that these are in any great order like they're kind of in alphabetical order but then there's a big chunk of
01:40:03that'll call on self will it probably not i don't know ruby lets us do a lot of cheap independency injection let's say that there's no way to Yeah, I don't need to do an injection. Turn that off. Injection like that. So I'm going to just stub it.
...50Global variable.
01:41:01Except I was trying to get out of the global variable, and this wasn't I. If the user is a global variable,
...25Right, so I made this, so okay. We'll couple to the global variable and then in the cabinet index.
...45Actually in all of these things.
01:42:02I'm missing the do.
...09What are you mad about? Wrong number of arguments. I gave you an argument, you just didn't, oh, I moved the do in the wrong place.
...51Let's reduce how much I'm retyping. So that's working. And then let's go back to this detail.
01:43:50It's the do this so rarely.
01:44:15This is very old. There's a newer way to do this of I want to define a method on the object.
...30Define singleton method. Oh, here we go. I thought it was.
...41So I should be able to say this is not something you would do in regular Ruby code.
...58It's going to fail, isn't it? Because if I return stuff, I'm just right back into hell, because not deleted is a scope I want to call. I'll just skip it. No, actually, this works. All right, story with merges. Visible merge stories with a user. And I will just go ahead and return.
01:45:29These two objects. And this four presentation is probably going to fire. Define local variable or method story without merges. How do you not have access to this? It's in scope.
01:46:03I mean, I guess I understand why it's not closing over that variable, because I'm doing something awful, but it's inconvenient. I want to do something awful.
01:47:09I'm just gonna place folder.
...25At least it'll probably blow up in a useful way. Let's see.
...37Captured a syntax error. That's a... What did I do here? Are we mad about that? I guess. Did we stick out rid of my red in the BIM? Alright, so that's better. Define method userPath. For the mergeStory.user. Yeah. Because that's just going to be...
01:48:11That should be a user model.
...28One of these days I want to make my own Ruby web framework. Oh boy.
...43and then I'll start my own Ruby web conference, right?
...51But I guess not in the US. Keeps coming back around.
01:49:21So it's funny, it doesn't fail up there. It comes down here. Oh, because there's this, it's a method, it's not actually calling it. So what's, I can't fucking debug.
...59Stories. It is a user object. 781B18. No, it's a different object. What is this object?
01:50:31Why can't I see it mentioned in the source here? If I print this twice, am I going to get two different user objects? No. So somehow, When this line calls MsUser, it's got a different object. Let's try that inside. But it shouldn't. What is getting passed?
01:51:24Missed detail line 86. Is this exception actually coming out of this avatar image? No.
...49Somehow it's Rails magic biting me and I don't understand why I'm getting bitten.
01:52:18should just give me the 2590 still a different object id he's calling user path
...48And I have a noisy garbage truck in the alley destroying my ability to think.
01:53:12What happens if I delete this line? OK, so is. All right, so I am overwriting that correctly.
...37OK, so it's mad about this.
...44If you give a model, Rails tries to infer the route to call on it, if I call the route correctly. Yep, okay, thanks, Rails. It was creating user's path instead of user path. I guess it was confused because it got an object that wasn't persisted, and it's like, wait, you're not coupled to the database?
01:54:17When the rails magic works the expressiveness is lovely when it doesn't. I wonder why i'm not reading Python.
...35All right.
...46this one is failing to render my oh it's not on this yeah on home page okay so these seem fine all right all right so All of this... And now I can do what I actually came here to do which is... These icons are redundant.
01:56:03Let me throw in the bumper of
pushcx This is Lobsters office hours, you can ask questions about the site anytime.
That this is Lobster's office hours.
You can ask questions about the site anytime.
And I'll throw it in chat so folks see it.
Great.
So let's find that icon.
...30That is at the beginning of the line.
...39So I can just delete it.
...46better. Maybe it's time I split this out into its own template instead of reusing list detail with a bunch of if around if single story. Because I had talked about handling
01:57:17the three of these together. And if I want to change that first one, I'm going to be repeating this if and this if single story.
...34Yeah. So, OK, we check it one, two, three, four, five times. That really is just kind of screaming that these are two different views with different purposes that should be split out so i'm gonna do that let's put this back i'm gonna first i'm going to what is the diff that's fine it's just hanging this in line partial if i reload goes away yeah so in case anybody doesn't get why the repo is changing out from under me heinous inline partial copies and pastes this partial into other templates as a performance hack and it only runs on reload because i don't have it wired up to a file watcher in dev because that seemed a little too magic and in prod it only happens once on server root so Let's look at the single story view.
01:59:05So instead of rendering the same template, let's just extract the things that relate to single story. I'm going to double check. Yeah, so this one passes true, and nobody else does. So if I copy and paste in the list detail, then I can refactor single story out on both sides. And that is exactly what I'm going to do. Wait, this one says true? Why do you say true? This must be preview, right?
...58Tisone. Why does zone do that because it wants you to see what you're doing it should instead just render well it wanted to show you without the comments i guess no the front end is doing it in line is doing an inline replacement. All right, let's look at that. Yeah, I think if I just delete this so that it becomes a full page reload with that link post, that's a better experience. Or at least it's just less code. All right.
02:01:18So this becomes a link post called disown that goes to the story disown path. Disowner form, why is there a separate class for that?
...42Because we target it in the JS, but then what's this CSS? Just making it inline.
02:02:02Yeah, makes it inline and then styles it to look like a link. This is just a bunch of repeated styles we're doing. That can be a link post. So this goes away and becomes confirm with this message. It's the same for story and comment. So we'll just change story for now.
...49And if I go look at a, is there a story this user submitted? Let's just submit one so we can see it.
02:03:37It's not old enough for me to disown it.
02:04:06I see the disown.
...14Story.disownableby. Okay, it's deletableDays. DeletableDays times two. Oh, okay, so not 14, but...
...49Good.
02:05:37Whoa, what the hell did I just paste in? So long, John Inquiry.
...49Vim. All right, Vim.
02:06:00I must have had that register. There we go. That's what I meant to paste.
...20Don't like that, huh? Do you want this in brackets?
...34I have an extra end from that mis-paste. No, what the hell did I do?
02:07:05I'm going to put that back.
...34Let's put in the syntax error. You are complaining about the ERB in the list detail.
...53You're mad about this line, right? You're mad about two things. OK, wait, so here's the end, which matches this if. It's not all getting indented correctly. So I'm going to delete this.
02:08:21OK, now it should come back. Yeah. And you're mad about that stuff, right? I'm going to try and add these back one at a time.
02:09:04Oh, there it is. I changed one of the quotes. I must have accidentally undone. OK.
...19So that's better. And now I need to re override the link style.
...49the color and the text decoration. All right. It's just not specific enough. Hang on. Why is the other one winning?
02:10:15Input type is submit. Text decoration is underlined.
...26How is this coming from? Put type is submit on a link post.
...45So this is more specific because it has a
02:11:12Alright, little pause for an allergy attack there.
02:12:09This is what I want to take precedence.
...21It's not because this scope thing. All right.
...41now they have the same specificity and the other one is where so this is line 228 and then this is line 196. So if it comes later, it should get overridden.
02:13:36Why is it not getting overridden?
...48So I'm not super familiar with this nesting module syntax. And I'm guessing that that's what's going wrong. So let's just get rid of it and see where that gets me.
02:14:08Nowhere. Why is this later one? All right. Is the class getting applied? The class is not getting applied. It has link post. It doesn't have. All right. So it's a bug in the helper. Let's put this back.
02:15:08No, it's form class. Wait, is the class on the form? Also no.
...29It's just not used. No, it's put on the submit tag?
...51But it wasn't. Why is that getting lost?
02:16:08Because it's passed as class underscore name, not form underscore class.
...25Now it has the class disowner form. And that still doesn't land. So many layers. So that's wired up at least. I don't know which of these is firing. So is it this or is it the other one? Okay. It's this one. Good.
02:17:47It's styling the wrong thing. It's styling a button instead of an input type equals submit.
02:18:07Does this even have a type? Yes.
...32If this is it, I'll fix the indenting in a second. It's a dash, not an underscore. So many ways to Have subtly wrong CSS. So few ways to have subtly right CSS. Okay. Now that's styled correctly. Now if I click disown, I should be taken to the single story view. Yes. With it disowned, yes. Good. Good. All right.
02:19:36Alright.
02:20:11Now I'm just going to remodel this where.
...23So now instead of using this. Like this path is gone for stories. Yeah. Good. So that's part of that last commit.
...48Let's run the build before I get too far. And while that runs, I will do my usual bumper that this is Lobster's office hours. If you have any question about the site, you can pop up anytime. If I build failures, I will fix them like I do now.
02:21:12Oh, I had a spec for disowning, didn't I?
...27Yeah, so this changes. And this goes away.
...44And then what else failed? So 308, 315, 308, this one failed.
02:22:22so it sort of changed from inactive to user and it didn't change what did i just delete oh i found all right hang on i did actually delete an extra line of code there the actual line of code that should delete it. There we go. Or disown it. That is a good spec failure, because I deleted too much code. Good. And then what failed in the story model? Specs.
02:23:21Nothing now. Green build. That's weird that a controller fixed a model spec. Didn't I see model in the file name?
...42All right. I'm suspicious. Let's scroll back up.
...49Ah, no. It said features. Okay, so that's the same thing. Disowning story. Okay, that's fine.
02:24:08All right, so now there's disowning tidied up.
There's less JavaScript.
And now I can say,
just kind of pop in the stack back to what I was doing 20 minutes ago of instead of rendering this partial, let's inline this partial and then simplify all of this because now the only references to single story being true should be along this code path.
So there's list detail, and there's show, and then this is repeated with list detail, this is repeated with list detail, and then the cabinet, which is our testing.
So, all right.
NoGoodNick_ is this ruby on ran?
NoGoodNick_ rails?
The fact that the cabinet wants to render that in isolation, I guess I will keep it as its own separate partial.
So let's save this as
NoGoodNick_ oops
Ruby on RAN?
Yes, it's Ruby on Rails.
And I gripe about that sometimes.
So let's, instead of rendering list detail, we will render single detail with the story.
02:25:41NoGoodNick_ do you work on other stacks also or mostly stick to RoR?
And a lot of this is just going through gyrations to make the view reusable enough that I can actually see...
I can actually render a view in a reusable way.
No, it's been a while since I've worked on another stack.
Almost a year.
When I worked at Stripe, I used their stack, which is Ruby but not Rails.
And then when I worked on IndieHackers last, it was...
NoGoodNick_ year is not that long
It starts with an E. A JavaScript framework that I did not enjoy and I've forgotten the name of.
Ember.
No, I suppose it's not.
02:26:50NoGoodNick_ ember doesnβt have a lot of fans these days
NoGoodNick_ Iβm new to web dev after a long time doing other things
What stack do you work in, Nick?
Ah, nice.
Wow.
NoGoodNick_ so Iβm starting with the popular thing of next js
Welcome to web dev.
So this is just going to be true on the left.
02:27:31Yeah, it certainly is that.
Can't fault you on that choice.
Get rid of that redundant end.
NoGoodNick_ one project next js, another is vite react and hono
And then reload this.
That's fine.
I've started removing it.
So this becomes if false, so this whole thing's going away.
What is HONO, H-O-N-O?
I know Vite React, but I don't know HONO.
02:28:29NoGoodNick_ light server side framework like fastify
Hmm.
A light server-side framework like Fastify.
I also don't know Fastify.
NoGoodNick_ newer and lighter than express js
So I've only done a little bit of JavaScript server-side.
And I don't know what to say.
I did not inhale.
02:29:07NoGoodNick_ haha
NoGoodNick_ well Iβm using TypeScript, if that matters, though if youβre using ruby then maybe it doesnβt
just send in a quick text there if it's a single story so this is true no this one is reduced to just if it's disownable this one is also reduced to if it's disownable this part of this goes away
...38yeah well i certainly like typescript more than i like regular javascript so let's get rid of this and now we're doing the reverse edit on the right side where this just And that goes away. This also can start using the nil propagation operator. This goes away. This goes away. And this goes away. So these two things, these two views can now diverge a little more easily. And we'll see how sad I get that these have diverged. And does this load? No. Oh, because now I'm passing a
02:30:59Yeah, when I was working at Stripe, one thing I did like, speaking of TypeScript, was using Sorbet, which was very similar to TypeScript in that it's adding type annotations to an untyped or a dynamically typed or a unit typed, however nitpicky you want to be, about CS terms, language.
02:31:30So now this view should render, and it does. And so let's also update that text on the cabinet page to say story single detail.
...52And I'm going to pull that out, bring it down here, and throw an HR in to separate them.
02:32:06All right.
...12And let's avoid wood gunning myself. Let's leave myself a note. I'll never see this comment. It's not going to stand out.
...57beats nothing.
02:33:09I'm actually going to make that its own commit because then I'll be able to see the edits around the merge view better.
...37And now I'm not going to edit list detail. I'm only going to be editing this single story view.
...53And not this one either. I'm more interested in this one where it's a merge story.
02:34:05All right.
...16So now this is dead code because it actually should be dead in list detail. It shouldn't be possible for the top level thing to be a merge story.
...37Because you get redirected if the top level thing is. Let's double check the cabinet. Yeah.
...56right and now what i came here to do was get rid of that icon
02:35:24And I guess what I want to do is say, well, let's put this up here and then put that there and say, on its own line, this is going to be, people are going to get mad if I change the title like this. So let's look at what it looks like and see if that's a benefit. Is it clear what's happening here? That's not bad. Yeah. So they have the same title. And then what I really want is to give them the same treatment because the other UI improvement was even if I remove the merge icons, put the submitter of the first story. So it's treat all of these the same.
02:36:23So I guess what I really want to do is, say, loop over the first story and its merged stories so that I don't have repeated things. And I don't want to make a partial. I mean, I could make a function. God, can I do that in ERB? So I would have a function, and I would drop out of ERB into the method body. All right, I'm going to step away for a second. I'll be right back and we'll continue.
02:38:31All right, this refactoring is really happening one inch at a time, story merging. Especially with the way I'm only working on it a little bit every week, but that's okay. So let's see if I can do this. If I said
02:39:01Can I define a method like that? Yeah, all right. And then s. I said init, I said s. And then down here, I said storyline with s and storyline with s. Well, let's say three and... It's just debugging. I just want to see that ERB will let me do this syntax. Okay. So I'm only doing this. Let's explain why.
02:40:21Let me think about this. Actually, can I? So if I said visible merge stories, who uses that? Just the one place I added, right? What if I just had the controller do it? So instead of this rendering a story and iterating over those things, I could just say stories colon.
02:41:09Right. And then I wouldn't need that. And then I'm just going to. assume I'm given the data structure I want instead of knowing something about the model. That's not bad. So here we find this story.
...41If it's merged into something else, we throw it that way. We preload all this data. So we'll just leave atStory as the top level thing. And then here,
02:42:34I think that function is about to go away.
...44So I'm only calling it from the one place for testing. So if I said that
02:43:15And this goes away. And if I don't need that now in the cabinet, instead of having to stub it on Singleton, I can say
02:44:08this tense save down here we will pass let's just call it let's keep it called merge stories It's merged stories, which I can just do that. And then story index, no, story show gets the same treatment.
02:45:16And now this becomes, instead of special casing story object, this is going to become here. I'm going to loop them. And get rid of this because it's duplicating the later stuff.
02:46:33All right, so these are all just variables that are getting used, so let's yank them out. Oh no, this is all just classes, isn't it? Yeah, all right, so there's that nice, there's a Ruby idiom for adding the classes that I'm not remembering. Like if I say, no, I can't do a turn area here, can I?
02:47:42There's some clever Ruby idiom I'm not remembering.
02:48:19Is it, if I say... No. That's it. That's basically what I want. Alright. There's a nicer idiom for it, but I don't remember.
02:50:25All right.
...56pushcx https://github.com/lobsters/lob…
That's funny.
I keep going back on the story UI.
And if you look at the actual issue, one of the things I said was the data model is wrong.
We have to treat the idea of a story with merge stuff as a different object than each individual record.
And we're seeing this over and over where the first one is special in a way.
But really, the first one wants to become
be the story object and the other things want to be attached records.
And now instead of
Here, we're going to say mergedStories.each ms. And all of this goes away because it's all repeated, right?
Well, the markdown description is going to have to get handled.
But title?
Yeah.
title gets handled all right so let's unify these
02:52:56Thank you.
02:53:33This goes away on the single story view, because if you can load the page, that's handled up in the top part. So there's that.
...50And then after the title, go the tags. Then after that, the domain and the byline. Boy, there's a lot of difference here. And then after the byline, I'll put that text, whether it's been removed, which
02:54:33It actually encompasses all of this.
...49And on each one of these, after that heading line, check if there's a description.
02:55:06And that comes in after all the avatar stuff.
...21Previewing is going away. Well, no, it's not. It's staying. Because that's what gets rendered for the preview. So if you're saved, this is all byline, byline, byline. Oh, man, where's the? And after that, you might get a description.
...56Description is often called the story text.
02:56:14NoGoodNick_ I have to go pack for my flight. have a good stream
What else do we have?
This is tags, we've already done that.
Oh, hey Nick, thanks for dropping in.
Have a good flight.
Then if there's an origin, oh, that's actually just a bug because that's what should be down here.
...44Yeah.
02:57:26We'll get some errors. That's fine. Undefined method is hidden by cur user. Is that a helper? Oh, the reference to cur user tells me it must be a helper, whereas Search index.
02:58:10No, it's an attribute on story. It's not a change. Yeah. So these are just virtual attributes on the story model rather than methods.
...34Define method story. Yep, that becomes if ms. So you shouldn't see the links. Good. Define method storyline 64. Now 76.
02:59:13Seeing that breakdown between what's a story and what's a link.
...2185. This is like type-driven development, but it's just typo-driven development. Statler and Waldorf, right? MS previewing.
03:00:23Yeah, so like this, hiding and saving wants to move up to the top level, which I guess is story. Then these individual links really want to be their own objects. Maybe I call it a story link. I don't know.
03:01:10all right this is outside the loop isn't it am i missing the end for this loop so this loops down to there but all of this should be in the loop because the point is i'm unifying all of this oh but You really only want to hide and show once. Yeah, so this byline, hold on. Let's grab a random story.
03:02:11So this has an author, has an avatar, done. And then if you're previewing, this should go up here.
...33And you have a styled user link that's duplicated. And then the how long ago is. That's the same code. So if you're previewing, you get just now.
03:03:25The story is editable. That's already there. I'm going to separate all these out. So when I'm doing these kinds of giant surgeries to ERBs, I'm especially frustrated that there's no way for ERB to validate your markup.
03:04:09because there is no way that all these open and close tags line up properly.
...28That's actually duplicated. The other one was wrong, so there we go. Am I missing a... I did get rid of a span, so I must have accidentally gotten rid of an extra one. Yeah, so there's the byline, and there's the heading. Okay. Don't know what the difference is between a heading and a byline, but we got it.
03:05:21All of this comes up.
...31It's not gone. So wait, if it's gone, you just don't see the UI for flagging? There's no way this logic is correct anymore.
03:06:09We know there's a user because the outer thing tested it.
...43Let me get into another. I didn't take the end. This is duplicated. No.
...58It says it's saved. Yeah, so this can just become else.
03:07:31And I'm logged in. What order are these in? Edit, mod edit, flag, hide, save. Caches should come next. I'm trying not to break everyone's muscle memory. So let's take that out. Caches underneath.
03:08:04And then what else do we have?
...12Comment count, so I. Don't want to have the well.
...26I don't want to have a comment count here. I want to have one all the way at the top.
...44So let's go up there. There's that stuff about the title.
03:09:21I'll do that.
...59Each. This only wants to be a link on the list detail.
03:10:23Right?
03:11:28That's so fun.
03:12:07Give that a second to come back to. There's one more thing down here to fix or to bring over.
...33This is the one that's the loop, right? And then there's a mobile comments path. That just goes away because that's for list detail. All right, let's see if this even wants to render. Wow, it rendered. Wow, I did not, I was sure there was going to be like a broken variable reference or a syntax error. Like that's a little ugly. All right, so we got an n plus one, but like that basically works and that's basically what I want to see. That's what progress. Okay, so styling, I lost the details class there. All right. All right, so let's, There's an extra new line or a line break creeping in. Let's go one at a time. There's this br. That I guess is extra because we... Yeah, so that's extra now.
03:14:08No, it's not extra. So each of these wants to be
03:15:25now each of these i don't know if did i lose the byline no i think each of these is the details rather than details of all of these my kingdom for a proper markdown and enter That's close to what I want.
03:16:26So instead of doing this inline, I want to just which I look at this. There's a span. Then a span and then a div byline. And I changed the div to a span. Or the merge story view did. Good. And now speaking of indenting, I'm clearly opening, opening, opening divs and not closing them in the right place.
03:17:26So the style is getting funky. So one of these. I mean, I could see a span here that doesn't get closed. Does it? No. So all of this stuff is in here.
03:18:01What are you closing?
...20So here's span tags.
...55All of this goes up here. This is just an extra span tag now. It doesn't ever get closed. Better.
03:19:28Just got to fix the indentation manually. So we have this details. Details has a bunch of stuff at top level. And the second line of this is the byline. So all this is byline.
...58except this block. It lags.
03:20:30They're present at the end. What are you closing? Who knows?
...52But that should be closing the byline.
03:21:00Wait, so we have details and then we have byline.
...16Picked up an extra end somewhere else. End.
...32Yeah, it's basically impossible to edit ERB and have valid HTML once you get to a certain level of complexity. And it makes me sad.
...55So this matches up with this div, and this one Doesn't get matched.
03:22:13So there's a list item. Why is there a list item? Just because it's styled like list detail.
...32Very close. That's basically what I want.
...42This heading is wrong, but
03:23:05Let's grab this, say.
...34See that's wrong. Merge icon.
03:24:07This also needs to go in there.
...23I don't even want to think of how many tests I'm going to have to write for this.
...45Actually, I don't know that I need this because there's the summary line. As long as that summary is there, I think we're good. Oh, I guess it's gone. There was a... It's probably just messed up the summary line of, oh, it's the unread comments count that's only for logged in users. And I'm not logged into prod here. So that's why it's missing. So let's just put that back. I'm showing stuff off screen because I'm not thinking. Anyways.
03:26:21Story single detail. Supposed to say the number of comments.
03:27:02i got it backwards wait a minute here let's wait if it's supposed to be printing up here let's just say sdf3 What is wrong here so it's printing on them. it's not on the one that's.
03:28:21Something about this is gone.
...44So what's catching my eye is that the single story here is missing all of these links. Why? Byline should always be present. Since we're seeing the link at all, we know we're in here.
03:29:36I'm missing something. I'm missing something clear. That even though I'm not special casing the story with one story,
03:30:07somehow accidentally special kissing it.
...47It's like I have an extra if somewhere. I'm inside the extra if. And I'm just not seeing it because I've been staring at this for so long.
03:31:07STF, right. So it's there. It's printing the line. And then after the just now, it's going wrong. So asdf is present.
...37And now it's present here and here. Good.
...57Coming off of the shift fast enough. I'm getting tired and making dumb typos. It's present. Let's just get these both on the screen. Oh, is it the if msgone and user? Yes, because these are the user controls, and I'm specifically doing that one as a visitor. That's what's wrong there. That i'm a visitor and the visitor doesn't see all these per user things okay wait that's actually fine. So this should be in. This should be in because you can't hide well that's fine to show actually.
03:33:11Fighting for screen real estate in 1080p.
...55Thank you.
03:34:53It's this one thing with merge stories that's wrong.
03:35:26I'm so far nested I can't see the if on the same screen. So I know it's not gone.
03:36:02yeah have everything except the comments count where am i accidentally checking if there's a user
...45Then this one.
03:37:20you
...50Thank you.
03:38:27There, but not.
...57There's an extra check here somewhere that I'm not spotting for the current user. And it must be hiding in one of these Booleans. And what I would really love is, can I
03:39:39It's not doing that right.
...53Span, span, div to end? That's not right.
03:40:13Apparently it was. Or right-er. Enough that the browser could do the right thing.
...28That's not an extra div. Nope.
...41I'm going to, I think, finish this one off stream, get some lunch. It's almost where I want it, but I just can't see it because on the stream I'm kind of peering through a peephole at everything. All right, so if you have any last questions about the site, now is a great time to throw them in. Otherwise, I'm going to wind down the stream. Take a walk, come back, spot the dumb typo or mis-indent that I'm missing. This has been a Lobster's Office Hours stream. The next scheduled one is Monday at 2 p.m. Chicago time, so you can drop by then. Otherwise, I will see you around the site. Take care, folks.