To make amends,
@digitalocean
donated $5,000 to an open source project of my choice. I chose Stimulus Reflex,
@hopsoft
and team have done an amazing job. What a classy move DO, thanks!
Why do I have no plans to restart RailsCasts? I produced content that I personally wanted to watch. I scratched my own itch, and the itch isn’t there now.
The more I work with Ruby the less metaprogramming I do: Monkey patching, method_missing, respond_to, instance_eval, etc. I will often prefer a more direct approach even if it means making the code more verbose.
If you make something that you personally want and can’t find anywhere else, chances are others will want it too. This is how RailsCasts became successful with zero marketing.
Anyone else have difficulty reading Ruby code that makes heavy use of modules? I have no idea where a given method is defined or what methods are available in a given context.
It is often said Ruby is optimized for programmer happiness. I say it’s optimized for short-term happiness at the cost of long-term happiness. A joy to write, but can be difficult to maintain.
My programming journey:
- Early career: Copy & paste code that does almost what I want then modify it.
- Mid career: Reuse existing code whenever possible to stay DRY.
- Late career: Copy & paste code that does almost what I want then modify it.
Active Record callbacks that trigger other callbacks are very difficult to debug. To avoid this, don’t save models in callbacks. You can also use services instead of callbacks to be more explicit.
When closing an issue/ticket due to user error, consider opening a new issue to improve documentation or to make the interface more intuitive to reduce the chance of the error happening again.
Dividing code changes into Git commits is a skill that improves over time. It can be challenging at first to make small, meaningful commits that keep tests passing.
I need to call Jury Duty every evening this month to see if my number is mentioned, so naturally I hacked together a Ruby script to do it for me. It uses Twilio to call, transcribes the message, and texts me the result. Here’s the gist:
Passing a boolean to a method is a code smell. There’s often a conditional shortly after that uses the boolean. Try refactoring the code by making a separate method to remove both the conditional and the boolean.
I’m impressed by Goldiloader. I recently added it to a large Rails app and it made nearly all `includes` calls redundant and solved quite a few other N+1 queries automatically.
The hash shorthand is my favorite addition in recent Ruby. {foo:} instead of {foo: foo}. It makes passing named arguments around so much more convenient.
I recently watched this excellent video on agile team organization and recognized the voice from a Minecraft dev video. I did not expect some of my favorite things to collide. You made my day
@henrikkniberg
!
If you’re using VS Code, the Alternate File extension is awesome for quickly switching between Ruby source, specs, and view component templates. I should have used this sooner!
Update on
@digitalocean
: They sent a thoughtful apology and are willing to continue sponsoring RailsCasts. While I do appreciate their years of sponsorship in the past, I have no plans to go back to DigitalOcean.
If an idea doesn’t stick well enough to be implemented now, don’t be afraid to toss it. Good ideas tend to float back up to the surface in a muted state that stays relevant.
Git Tip: Running `git checkout -` changes to the previously accessed branch just like `cd -` changes to the previous directory. You can use it with other commands too such as `git rebase -` to rebase off of the previous branch.
I’m setting up a new MacBook Pro and accidentally put my mouse on the edge of the screen. The mouse showed up on my other laptop! Dragging files across works seamlessly too. What is this sorcery?!
Oops, I ran `brew upgrade redis` to upgrade Redis and it’s upgrading every package under the sun. Apparently I should have run `brew install redis` to upgrade Redis. 🤦♂️
@ShinoKouda
The solution? Keep inventing new places to put logic. Start with PORO. Abstract it into a complex framework. Decide logic doesn’t belong. Rinse and repeat.
Command line tip: Do you ever forget what aliases you have set up for commands you run frequently? Running `alias` without any arguments will list them all. Pipe this to fzf for easy searching: `alias | fzf`
When writing business logic, I used to favor POROs (Plain Old Ruby Objects). Now I prefer class methods and extract POROs through refactoring. I still keep the class method around as the interface for the logic.
Verbose code is often viewed as a negative, however being overly-concise is worse when it hides important details needed for debugging and understanding the code. Dependencies, state manipulation, and namespacing are all areas I prefer to be verbose and explicit.
Five years ago today we lost
@jseifer
. While I only met him a few times, I’ve always appreciated his sense of humor and the joy he brought us through it. Here are some of the skits he did with
@greggpollack
. May he continue to make us smile!
Software development is like casting a 3D object onto a 2D plain. Attempting to model every aspect of a complex domain can become a mess. First choose an angle and build a beautiful representation of the domain that is intentionally limited for the software medium.
I surround code changes with two different types of refactoring: pre and post change. Pre-change refactoring is to make the change easier to implement. Post-change refactoring is to make the code easier to understand.
It’s nice that RubyMine helps read code that makes heavy use of modules/mixins, however I wonder if this furthers the problem by masking readability issues. A good goal is code that is easily readable outside of an IDE.
Attempting to satisfy the requirements of different types of users through a single UI can lead to a sub-optimal experience for all users. Consider splitting the UX (or even the entire app) around the type of user to provide focus and reduce the requirements.
How I stack pull requests in GitHub:
1. Enable “Automatically delete head branches” under General settings.
2. Set base branch when creating stacked PR.
3. Merge bottom (oldest) PRs first. This automatically changes next PR’s base to “main”