I created a web chat app in a week: my fastest Rails project yet

A pixel art image of a sunset, with mountains and buildings

I gave myself a goal: one week, one Rails project. And that I did. This one is called Evenfall. It is a real time chat application where people can make rooms and type back and forth. Is it reinventing the wheel? Yep. Is it going to make a splash? Nope. Did I learn a lot? Yep. As you’ll see, the biggest challenges did not come from the networking part of the chat, but rather making it not annoying to use.

This project started on July 23rd 2025 and ended July 30th.

Some context

Evenfall is part of a series of projects called the 1212 learning process. For this I am learning Ruby on Rails in an attempt to get past my nasty habit of overthinking everything and instead just get stuff done. You all know that over-thinker. You might even be one of them.

Anyway, to give a high level overview, here are my projects I completed as part of the process:

βœ… Complete a project within 1 month (Bloggington) (~60 hours of focused work)
βœ… Complete another project within 2 weeks (Phasmid) (~50 hours of focused work)
βœ… Complete another within 1 week (This project, Evenfall) (~33 hours of focused work)
🚧 Complete a final project within 2 days

For those who want to see the repository as it was after just the 7 days, refer to the legacy branch of the repository.

The end result

This is a quick 1 minute demo on creating a chat room and doing some simple back and forth chatting. I use two separate browsers on two separate accounts to simulate the interaction.

How it went

Day 0 – Strong start

I did the usual day 0 things. Got the Github repository up. Ran the convenience scripts to get things like authentication, ActionText, and the models in order. The database schema was simple this time, and I did my fair share of wrangling models during Phasmid, so it was easy to get a working database skeleton working in short order.

Day 1 – Plot twist

I got real time messaging working. This is huge news given how early it is in the project. I do want to elaborate on this a bit, as it is kind of the core gimmick of the whole project, and yet said gimmick was complete in 2 days.

How was this done so quickly?

This was done using ActionCable. This comes with Rails and makes it incredibly easy to incorporate real time updates pretty much whenever your business logic wants to. I will admit, I did use ActionCable when writing Phasmid so that contributed to my headstart.

Real-time messaging works in 3 major stages

  1. A message model instance is created
  2. A broadcast is triggered, sending the message’s HTML contents to a subscription
  3. The room that has the subscription receives it, and displays it in real time.

Here is the entire Message model in my project (edited slightly for formatting):

message.rb

class Message < ApplicationRecord
  belongs_to :user
  belongs_to :room
  has_rich_text :content

  after_create_commit -> { 
    broadcast_append_to "room_messages_sub_#{self.room.id}",
    partial: "messages/message",
    locals: {
      room: room,
      message: self
    }, 
    target: "messages"
  }
end

The important part is after_create_commit, which essentially does the following:

  • After a Message instance is created (AKA anybody sends a message), send a broadcast to all subscriptions associated with this message’s Room. For the purposes of this project, only one subscription exists which I will mention shortly.
  • partial refers to an HTML “chunk” which will be appended to a target called "messages". The target refers to the id of a div that is located in the chat room.
  • locals passes along the information to be used when appending the message data to the target div.

A moment ago, I mentioned a subscription that will receive the broadcast. This is where the subscription exists:

_messages.html.erb

<%= turbo_stream_from "room_messages_sub_#{room.id}" %>
<div id="messages" data-controller="messages" data-messages-target="messages">
    <%= render "layouts/flash" %>
    <p>--- This is the beginning of the chat ---</p>
    <% messages.each do |message| %>
        <%= render "messages/message", message: message, room: room %>
    <% end %>
</div>

The important part is the beginning, where we define the turbo_stream_from with the same name "room_messages_sub_#{room.id}" that is referred to in the broadcast_append_to line in message.rb. The second important part is the <div id="messages" ...> portion as this defines where the broadcast needs to append to (i.e. the target).

And for reference, this is the partial being broadcast, the HTML “chunk” as it were:

_message.html.erb

<div id=<%= combined_dom_id(room, message) %> class="room_message">
    <span><b><%= message.user.username %>:</b></span>
    <%= message.content %>
    <br>
</div>

I want to note that ActionCable is not perfect. If you are not actively looking at your tab, it’s easy to miss messages when you come back to it. While this can be fixed by refreshing, that’s obviously not very cash money of the application.

There are ways to improve this, such as setting something up to queue messages for you. Or perhaps you can use AnyCable, which is apparently a drop-in replacement of ActionCable with more stability/features. That said, I accepted the limitations of ActionCable in the meantime for the sake of moving my project along and not getting bogged down in trying to get an external library to work.

Day 2 – Making stuff look nice

This day was pretty run of the mill. A bit of HTML/CSS formatting to make things look neater.

Day 3 – Mobile, navbar, and early chat interaction logic

More stuff like day 3, as well as making the site look better on mobile. I made a navbar and edited chat rooms so that they will auto-submit when pressing enter. Chat room interactions start out simple, but the next day will show me that to get them precise is a different story.

Day 4 – Chat rooms are hard

So I did the thing where I underestimated the complexity of handling the intricacies of a chat room. Here is the layout of the chat room:

A chart showing a chat box with a submission form under it. The scroll bar is pointed out.

Here are the problems I had while making the chat room usable:

Scrollable elements in HTML start at the top and not at the bottom

This means that to show the latest messages, I have to auto-scroll the scrollbar to the bottom when the user enters the room. This was the easiest of the issues to solve.

When a user sends or receives a message, the scrollbar does not adjust

If the chat box has a new message, the position of the scroll bar stays the same. The message is “hidden” until the user scrolls down. This is of course really bad user experience.

Now, this could be solved by auto-scrolling to the bottom when any message is entered into chat. This creates a new problem though. If you’re looking through the chat history, you will get rudely interrupted every time someone in the chat posts a message. I could have invested time in a fancy thing that notifies you of new messages at the bottom, but the whole 1-week deadline said “no sir you’re keeping it simple.”

As a result, my simple solution was this: if your scroll bar is low enough in the container when any message comes in, then it will auto scroll down. This “low enough” value was definitely based on vibes. I settled at 200 pixels. This was eventually done on day 7.

Pressing return on the message editor does not send messages

This is an understandable problem. The Trix editor has no business auto-submitting forms when pressing return for a multitude of reasons. However, my app certainly has that kind of business. Fast paced messaging is the name of the game.

But of course, we still want people to be able to create newlines. As a result, I needed to account for shift + enter.

It all needed to work on mobile

I made it a point to try and make this site mobile compatible. So all of the problems above needed to be solved for mobile too. Most solutions transferred over, but pressing return was the only way for someone to realistically create a newline on mobile, so I had to code a workaround for that on day 7.

Time to learn Stimulus

I realized that regular Javascript inside of the HTML was not going to cut it, especially when you have stuff constantly changing around in a chat room. Using Stimulus controllers made it far easier to keep track of the state of the page, and act upon those changes.

I don’t like how my controllers came out, and as a result I will not be going into too much detail about them in this post. The good news is I think the next time I write a stimulus controller, it will be far more organized. And perhaps more worthy of writing about.

Day 5 – Centering some divs

I spent the session centering the forms so they look good on desktop and mobile. You heard that right gamers, I centered some divs.

Day 6 – UX improvements

I made the login/register forms a bit more informative if the application has any issues with form submissions. like mismatching passwords and cases where username/email are already taken.

Oh I also added the favicon.ico

A small icon depicting a road going into a sunset

Day 7 – Cleanup

A lot of this was a continuation of Day 4: Chat rooms are hard. I got around to fix the remaining issues I ran into that day. The rest of the time was spent cleaning up formatting, applying max character restrictions on forms/models, and stopping the chat box from taking any drag-and-drop files other than images.

The numbers and conclusions

ProjectTime WindowHours Worked% of Total Time
Bloggington1 month (~730 hrs)~60 hrs8.2%
Phasmid2 weeks (~336 hrs)~50 hrs14.8%
Evenfall1 week (~168 hrs)~33 hrs19.6%
Project 42 days (~48 hours)TBDTBD

The time spent on Evenfall was past my initial expectation of about 25 hours, which instead landed at about 33 hours.

Interestingly, even though I spent a considerable amount of time during the week, I didn’t burn myself out. There was plenty of time for me to do other things most evenings like gaming or going out. Having a remote job also helps.

Given my practice on the first two projects, it is reasonable to say I was able to do just a little more in less time. Plus, I’ve found it’s more enjoyable to code using Rails now that I’m getting the hang of things. Great news overall.

The two day project will be coming soon. It will need to be on a weekend where I don’t have much plans, so it may be some time. But it will happen, and it will be the toughest challenge yet. My projects sequentially halved my available time. This final one is the outlier, cutting my time by more than half. I described it as such in my initial post about the 1212 process:

“Project 4: The Crucible (2 days): Your ability to very quickly get something out the door will be forcibly squeezed out of you. The shortest path to success is the only path.”

Time for The Crucible. Stay tuned.

I’m giving myself increasingly aggressive deadlines to learn Rails fast. Here’s what I built in the first month.

I did the first step of a challenge I set out to face in a previous post! As a quick summary, I planned to do the following to learn Ruby on Rails:

  • Complete a project within 1 month (The thing I did)
  • Complete another project within 2 weeks (To begin June 30th 2025)
  • Complete another within 1 week (Start day TBD)
  • Complete a final project within 2 days (Start day TBD)

For this first month, I kept it simple and made a “blogging” social app called Bloggington. The goal was not usefulness or complexity, but rather just implementing something straightforward to flush out the garbage that comes with learning something new. And oh my, was garbage flushed.

This project began on May 14th 2025. I stopped all work on the project on June 15th, 2025. You might find that this was technically a month-and-a-day project. That would in fact be correct. The reason for that is because I can’t count.

I published this server on the internet and shared it with people I know in my public Discord. It was surprisingly fun. For now, I am keeping my web server locked out from the public because image posting is a sensitive thing that I don’t intend to deal with currently. Anyone who previously made an account on it still has access.

The web application is open source though, so anyone is free to pull it and run it on their own!

For all the perfectionists out there

Like many, I’m historically bad when it comes to sticking to projects. Getting this first project out has been super gratifying, especially when I was finally able to deploy it and simply see it out there on the internet!

Separating something I made from how I perceive my value as a person is a skill I am currently learning. This project made it a lot easier, especially when looking at it from an experimental point of view, and with an actual deadline.

Yes, it looks terrible and that’s totally fine. The fact that I shipped an actual web app to the internet and had the courage to share it is what’s great! Now I can iterate on whatever information I gather.

My experience and the time I spent learning

I am a software engineer who specializes in QA automation using NodeJS. I’ve been doing that for roughly 7 years. I have basic knowledge of Python (having created only a couple things with Django and Flask). Both Ruby and Rails are brand new to me, but I do have some previous knowledge of model-view-controller frameworks.

I know the basics of html/css. I used Bootstrap for the frontend, but I can definitely see an argument that it probably wasn’t necessary. I do plan to improve my ability to use raw html/css at some point but that may be a little while.

For the purposes of this project, I spent a week on the Getting Started with Rails guide and then spent the aforementioned single month working on Bloggington. That is all of my exposure to Ruby and Rails.

How it went

Much of the first 2 and a half weeks was getting acquainted with the core navigation of a Rails application (The initial stretch). This includes learning to leverage the usual suspects in a model-view-controller framework. The next 1.5 weeks (The big hump) had a huge spike in difficulty which slowed me down a lot due to learning the Turbo framework, and then there was a decent uptick in productivity a few days before the end (The weirdly productive scramble).

The above is my commit graph. You’ll notice that the week of June 9th has a huge number of commits. This is due to 2 things:

  • There was a ton of experimentation during the big hump that I eventually got working; as a result, I committed a ton of stuff within a short time period.
  • Some of that week also includes the weirdly productive scramble at the end of the project.

Overall though, I was able to consistently work on the project almost daily.

The initial stretch (2.5 weeks)

This was definitely just picking up the fundamentals and understanding how they work. I didn’t generate any scaffolds using the command line, but I did generate some models. This meant that I had a very thin skeleton to work with and I had to manually wire together a lot of the simple CRUD operations around blog posts and users.

I have reason to believe that in my next project, this will be drastically shortened. This is made apparent by how much easier it was to make changes to the project during the weirdly productive scramble.

The big hump (1.5 weeks)

It all started when I wanted to add comments to posts. I even had the gall to desire comment threads. This little maneuver cost me a week, and I didn’t get to implement comment threads. Just top-level comments. I did gain some sweet knowledge though.

When I made the sweet-summer-child attempt at throwing a bunch of forms onto a comments page using a for-loop, I quickly realized that the page had no idea what to do with the forms. And turns out, neither did I. After fighting with form submissions for a good while and some looking around, I was reminded of Turbo’s existence.

You see, Turbo is briefly mentioned in the Rails Guide, but it’s definitely not a core component in the learning material itself. When I saw it alongside Stimulus I made the assumption that they were libraries just kinda used by Ruby behind the scenes with no need of your interference. That is in fact incorrect.

While Turbo is used behind the scenes in a lot of cases, a lot of it is definitely used by you, the developer.

After spending multiple days trying to understand Turbo Frames and Turbo Streams, it slowly began to make sense. Many times, I would have an assumption of how it worked, and then find out I was dead wrong and I was set back quite a few places. Even when I began to truly understand them, I found that I was still struggling to grasp why they are useful.

Basically, they make it so that it’s easy to turn a standard multi-page web app into one that updates on the fly like a single-page app. This can be done in a hybrid fashion, where some stuff is dynamic and other things will take you to a dedicated page. Or, you can theoretically use it to create a full on single page web application.

By the end of this phase, I was able to get Turbo frames and Streams working, where you can add/edit posts and comments without needing to go to a separate page. I did not have time for implementing nested comments though, as time was running short and I did not want to open another potential can of words as time was running out.

The weirdly productive scramble (0.5 weeks)

So once I knew enough about Turbo related things to survive and understand why it exists, the last few days were a lot easier. Part of it had to do with the relative ease that CRUD operations and model restraints are compared to Turbo stuff.

Most of this period, I picked up some things here and there without too much difficulty. I implemented profile pictures, learned about model helpers, used functions for validating models, and accounted for empty comments/blog posts. I also made some attempt at making the web application look visually parsable, though to a very limited degree.

The web app

This only shows some of the features of the web app. You can also register/login, edit posts, add/edit your profile picture, and look at people’s profiles where all of their blog posts are located. Ideally, less time will be spent on figuring things out in my next project, and perhaps more time can be spent polishing it.

Additional things

  • Any edits I make to the repository in the future will be on branches outside of main, to maintain the historical integrity of this fine (and crumbling) monument.
  • The repository had 56 commits total.
  • Roughly 60 hours were spent on the project.
  • There are no automated tests, aside from what was auto-generated by Rails.

My predictions and plans for the two-week project

  • Wiring up models, views, and controllers will take considerably less time.
  • Using Turbo Frames and Streams is a bit more natural now, and will take less time.
  • I know nothing about Stimulus yet, though I hope a situation arises where I can learn it and feel good about it. If it does occur, it may eat up some time.
  • I plan to use test automation for the next project, even if it is a little slim. I may do a little bit of reading and practice using automation on Bloggington (on a separate branch of course) before starting the 2-week project.
  • The actual project itself is unknown at the time of writing. I do have some ideas though.

And that’s it!

If you made it this far, then thanks for reading! While the process of making this first web app was definitely tough, it was absolutely worth it after I finally got it online.

The 1212 learning process

Without any ado, I’m going to discuss a new theoretical method, the 1212 learning process. The process is simple. Trying to learn new a new software stack quickly? Do four projects, each of which are your own choosing. They will be ugly, they will be painfully unoriginal, and they will be wonderful little troves of knowledge. You will spend decreasing amounts of time on each project:

  • 1 month on the first project
  • 2 weeks on the second project
  • 1 week on the third project
  • 2 days on the final project

These projects will most likely not see the light of day, but you will learn a bunch of things. They will also be distinct projects from one-another to encourage variety in your day-to-day problem solving.

Project 1: The Warm-Up (1 month)

This gives plenty of time to trip over yourself constantly at the beginning and not feel the immediate doom of a close deadline. Every mistake can be seen as a learning experience, and the time spent on hitches will be a smaller percentage of the total time you have.

Project 2: The Build-Up (2 weeks)

By this point, the small things should be easier to navigate around. More significant steps need to be made per day but there is still a bit of time to iron out any unexpected issues. It is possible that some polish may be foregone.

Project 3: The Refinement (1 week)

Efficiency combined with consistency will be paramount here. Some simple workflows may be second nature at this point, but now things are more serious. A bad enough setback could put you behind, but your skills from the previous two projects will help to understand the intricacies and work around the issues.

Project 4: The Crucible (2 days)

Your ability to very quickly get something out the door will be forcibly squeezed out of you. The shortest path to success is the only path.

What this is, and what this isn’t

This process flushes out the bad projects you will inevitably make when taking on a new tech stack. By setting progressively shorter deadlines, you’re pushing yourself to move. We want to see through the things that don’t matter and get to the core of what we want to get out of the door.

This process does not intend to produce any software of value. While happy accidents are always a nice possibility, they are not the intention.

Some last things

So you might be wondering, does this process actually work? No clue; I just made it up. The good news is that I’m currently working on my 1-month project, so I am on my way to understanding the viability of the approach.

The project is an aggressively simple one, create a simple blogging application using Ruby on Rails. It needs to be a straightforward, possibly ugly, but functional MVP. In theory, it would be something I’d use if I wanted to sell to the totally-niche subgroup who desperately needs yet another blogging software. My hard deadline is June 15th.

For the ultra curious, the project is available to look at on Github. At the time of writing, lots of stuff is (justifiably) missing, but stay tuned for progress on future posts!

Intermission

Alrighty, so a bit late this post was by my standards, but life throws things at you. You know how that goes. That said, I wanted to at least talk about some of the things I have been working on!

The Python Discord Code Jam

Recently, the Python Discord released a qualifier for their latest code jam! I have never taken part in a code jam, so I felt it was the perfect time to amend that. I successfully submitted my qualifier and while I regret to inform that it was not hyper-optimized, it definitely did the job.

I’m excited to see what sorts of ideas my team and I can come up with for the code jam. It’d be neat to place really well in the contest, but since it is my first one I’m really looking for the learning experience.

A super secret Rust project

Yep, that is indeed a thing I am working on. It may or may not involve Bevy and an additional developer. Stay tuned πŸ‘€

The media posting app

I still intend to try and Dockerize the Django application I have been working on within the past month and change. I only have some experience using Docker, so it’s gonna take a bit longer there. Once I have it in place though, I may have an easier time incorporating it into a Gitlab CI pipeline that I mentioned in my last post.

And that’s about it

Taking up multiple projects has certainly been an interesting experience for me, as I am still also trying to improve myself in other ways that aren’t just coding. There are even more coding-related plans that I have, but I’ll keep those under wraps because it’s harder to start them if I start talking about them.

Short post but we take those. Stay cool friends 😎

The Hard Part

We all get there at some point; it is an inevitability that precedes your next victory in some cases, or perhaps it precedes The Hard Part II in others. Regardless of the the context, it’s coming for you. For me, it’s here!

The Hard Part involves brick walls. It involves trepidation. It involves self-doubt. I’ve spent a lot of time improving myself now and I’m already aware of the signs. I’ve come to learn a few things and have started to employ methods of working through The Hard Part.

Old me would have said forget this. I’m tired of this. Thankfully, new me is tired of being tired of stuff. Instead, I’m going to type out what’s making things The Hard Part and what I’m doing to work through it.

So what’s makes now the hard part?

Okay, so I’m still dealing with the real-life issues that sparked my post from a few weeks ago. After rereading the post again, I’m glad I wrote it and I feel better after rereading it. That said, I think my personal issues currently reside within the Annoying Chore category, rather than the Hard Part. That’s not to say personal issues are an afterthought. I just think my progress in that regard is not something to be worried about. I know I’ll get there.

That effectively just leaves the things I’ve been working on. The main thing I’m working on is my Python Django web application. For the interested, I posted about it here and here.

Since the last post, I recently made some unit tests. I also set up some Raspberry Pis on my local network to do some things. One of the Pis hosts an instance of Gitlab and the other Pi is hosting a runner that works with the Gitlab instance.

The problem I am currently running into is the dumb little box in the bottom left area called “Gitlab Runner.” I’m trying to run the gitlab-runner service in the background of the OS instead of running it manually in a shell in the foreground. It has proven annoyingly difficult. I tried to use crontab, nohup, and shell scripts to get it to run in the background. All of the approaches did not work and this consumed a lot of trial and error to no success.

Now I’ve spent all this time digging into the technicalities of building a working pipeline, and there’s still tests to be written. There’s still product features that that I set out to do. There’s still a million things to learn just to get this clunker-of-a-learning-experience software in a state that I think is acceptable.

One realization I’m coming to is there’s a reason why software companies hire multiple people. Yes, it’s obvious on the surface. Seeing it in front of you is life experience. It turns out that..

  • Making the project
  • Making the tests for the project
  • Setting up an infrastructure where pipelines can be run against the project
  • Setting up the code environment such that the project can be worked on and tested locally while still being compatible with a pipeline
  • The deployment process and integration into the pipeline
  • Using Docker in general in the process
  • Doing other stuff I definitely forgot about

… all at the same time, is in fact a herculean effort.

I’ve always been someone who’s been indecisive. It annoys people. Ask anyone I know. I have to write posts like this to understand what’s going on. I sometimes wonder how “10x” developers do what they do without going mad. As a result of the challenges I’m facing, my mind is going a mile a minute without any sort of productivity as a result.

In these dilemmas, what do you do? I’ll tell you what.

How to deal with The Hard Part

Deep Breath

“Okay.”

Take a step back. What’s the goal I’m trying to achieve in doing this project? Nobody has expectations of me right now. This is huge. Sometimes, it’s easy to get lost in the details and then throw my hands up in frustration when something doesn’t work. That’s fine. Here, look at this:

“What is that?” you may ask. I can tell you what it’s not. It’s not the big picture. Stare at it too long and you start to conjure things in your head of its meaning and its purpose. “Why is it like that? This doesn’t tell me enough. The colors are cool I guess but they don’t mean anything.” Thoughts about it are inconsistent and erratic at best, based on conjecture and frustration.

This is where you have to step back and look at the big picture.

Big picture time.

What am I trying to do with this project?

What I want to do with my Python Django project is understand the process of going from idea to production. Anything more than that is fluff. Yes, I have some features/tests planned out for the project and that’s great, but I will say that the majority of the remaining features/tests fall more into Annoying Chore territory rather than The Hard Part territory. If I let myself, I could keep adding features/tests to the project ad nauseam and never be done, while The Hard Part is lurking, waiting for me to revisit it.

Instead of dreading the Annoying Chores and The Hard Parts at the same time, I’m going to focus on The Hard Parts only. Yes this means some features won’t get done and test cases will not be finished. However, completing those things 100% will not be conducive to a learning experience. Diminishing returns.

Disclaimer: this approach does not work outside the context of learning. The real world unfortunately has its own plans in times like these that are best covered in another post.

I want to learn how to Dockerize my project, run tests against it using a pipeline (even if they are bare bones tests), and deploy it to some local server. Those are the things that matter. I don’t need to think about anything else in the meantime. I have a project and the means to test it. Now it’s time to deal with the operations that work on those means.

Yes, this will involve banging my head on the wall with the previous issue I mentioned. Yes, there will be other challenges to face alongside it. But now that I’ve looked at the big picture again, it can at least be underscored with a sense of purpose.

And anyone who has gained a sense of purpose, however fleeting, will know how powerful that is.

That’s all I’ve got for today. Stay safe friends.

Updates, and when the real world leaks into the technical world

Over the weekend, I got to attend Triangle Code and Coffee! It was pretty exciting and I’m glad that I went. You always hear about how great it is to attend events that have a variety of people with a diversity of backgrounds and ideas. And it’s like, yeah, of course it would be pretty fantastic. However, actually being there for it certainly strengthens that perspective. It’s kind of annoying how often cliches are actually true.

If I were to give advice for anyone attending a networking event, go early. You’ll meet other fellow go-early-ers and by the time the event starts you’ll have people you can reliably approach. It makes meshing with groups a lot easier, especially if your go-early-er group is a decent size. That’s all I have for advice though; I’m still a programmer and you know how cliches go.

“That’s great and all,” you say while pointing at your watch, “but where’s that Python Django progress you were talking about last week? Don’t leave us hanging.” And to that I would say, oh yeah, you’re right just a sec.

shuffles metaphorical papers

The Django stuff

So this week I managed to make some considerable progress on my Python Django application. Admittedly, the size of the things I want to do increased in size faster than I could make the things. I understand if that comes as a surprise.

Last time I mentioned that I had 7 things I accomplished and 5 things I wanted to do. Now, I have…

  • 11 things I accomplished
  • 5 things I want to do as part of completing this project
  • An extra thing I decided to do in the middle of a programming frenzy
  • 5 things I’d like to do but I won’t strictly consider acceptance criteria for the purposes of finishing this within the current decade

To keep it simple, I will talk about the new and most interesting things I accomplished.

Following users and only seeing their posts

Given that the concept of following people is a many-to-many relationship, there was some database-related logic that needed to happen. Simply put, it was this:

Anybody with any amount of database experience will recognize this pattern, which is called a join table. These “following” entries can be created and deleted on the fly without affecting the users.

For those who are interested in the Python/Django representation of this, it is the following:

class User(AbstractUser):
    date_joined = models.DateField(auto_now_add=True)

class UserFollowing(models.Model):
    follower = models.ForeignKey(settings.AUTH_USER_MODEL, 
                                    related_name='following', 
                                    on_delete=models.CASCADE)
    following = models.ForeignKey(settings.AUTH_USER_MODEL, 
                                    related_name='followers',
                                    on_delete=models.CASCADE)

For those who may have noticed, User extends from Django’s AbstractUser class which has all the attributes you’d expect from a user. The attributes that you do not see (but definitely exist) are username, password, and email. For my particular use case, I added a date_joined attribute that allows you to see when the User was created.

The ForeignKey parts in UserFollowing essentially say that we are going to be pointing to a user for each of them. There are 2 entries for it, one for a follower and one for is being followed. Due to how Django allows you to access database info, any User object is capable of accessing their followers and who they follow by using the names described with the related_name parameters. A good example of this is from a function to generate posts based on a user’s following. This also includes the user’s own posts because it’s nice to be able to see your own posts too:

def aggregrate_tailored_posts(request):
    follow_relationships = request.user.following.all()
    posts = request.user.post_set.all()
    for relationship in follow_relationships:
        posts = posts.union(relationship.following.post_set.all())
    return posts.order_by('-date')

The posts returned from this function will then be passed to the HTML template represented by the feed. Then, the user will see their own stuff they posted, as well as the posts from people they’re following.

Improving site look with bootstrap

I put this off for a while because I knew that my creative eye can vary from “vaguely resembling insightful” to “trash can incarnate.” For a better idea, take a look at my pixel art section!

Self-deprecation aside, I was able to format the site in such a way that it looked like something a human could use. This not only applied to desktop, but also mobile.

In order to do this, I leveraged the different formatting classes that bootstrap has which allow for adjustments based on different screen sizes. As advice for those that are curious about Bootstrap, read into how containers, rows, columns, and how the 12-column system works. This will provide a solid foundation for picking up the rest of the things bootstrap has to offer.

Seeing a user’s previous posts in their profile (the extra thing I decided to do)

This next feature is very similar to the feed. The main difference is that the posts listed are all posts made by the user. There is currently a restriction where you can’t comment on posts when you’re looking at them from the user page. I may implement the ability to comment while on a user page but it’s not entirely high on my list of things to do.

Much like the feed, this is a mobile-compatible interface. If it sees that the user is on a mobile device, it will actually move the user’s card to the top of the page instead of having it on the left side like the image above.

Testing

Since my focus has been more on picking up the framework, I haven’t written as many tests as I wanted to. That said, I have a working test in Selenium which will login as a user and check that the main page is available.

I am currently running into an issue where I want to have a consistent starting database that would reset back to its original configuration after selenium tests are done. A little bit of work will need to be done there in order to not have to manually reset stuff before running the Selenium tests.

I currently have a Gitlab server set up on my local network, so I will be working towards trying to dockerize this project and set up ways to run the selenium tests in a pipeline. That will be the best time to address the aforementioned problem, as I can have everything running in neat little containers with their own scripts and things. I also need to look into the Gunicorn utility for hosting the site that will be tested against.

And that’s about it

I didn’t cover literally everything that I made in the past week since that’d be a pretty nasty-sized post, but I did want to get the important parts out at the very least. It’s been a pretty neat project so far so I’m hoping I can try and get at least the core parts completed.

‘Till next week!

Basically a devlog

I said I would do a post once a week and doggonit I’m doing it! I realized yesterday that almost seven days passed since the last post and my first reaction was “wow, how do actual professional writers do it?” Time itself decided it was time to be next week and here I am, at the mercy of it.

Jokes aside, it has been an absolute learning experience with Python and Django. Much like when I was learning Bevy, there was an initial phase of “this is confusing and has so many moving parts; how does any human function while working on this?” and then over time I started to think “Okay I want to do these things, so I just need to change this, and this, and this, oh and I gotta remember that. Why doesn’t this work? Oh yeah duh because of this.”

That’s essentially the sound of growth. Anyway, here are the things I recently accomplished so far with creating a sample media posting app in Python and Django:

  • Basic login/logout system
  • Making posts with images
  • Making comments on posts
  • Deleting your own posts
  • Seeing all listed users
  • Seeing user profiles
  • Editing own user profile

Here are the features I plan to add as well:

  • Following users and see only their posts
  • Making reactions on posts (ideally with ajax)
  • Full email authentication
  • Making things look nicer using bootstrap’s layout system
  • Automated testing

There are some additional nice-to-haves like lazy loading and real-time post updates, but we shall see on those. I ideally want to have those things but it won’t be the end of the world if I decide to move on to a newer project by the time I finish adding the things I definitely want to have.

One thing I want to do as well is construct a local Gitlab CI pipeline for the project. This effectively falls under the very broad category of “Automated Testing” that I listed above. The pipeline would ideally run my automated tests, then deploy to some local web server that I have. I’d be using my assortment of raspberry pis for this endeavor. I also want to use the Django unit testing framework as well as Selenium for product level testing. Therefore, “Automated Testing” will most likely take the most time out of the remaining tasks.

Anyway that’s about it. I hope to have at least have the remaining core features done by next week so that I can talk more about them. Thanks for reading and don’t do anything I wouldn’t do!