Avatar of Jerome Dalbert

Jerome Dalbert

Senior Backend Engineer at StackShare

Decision about Visual Studio Code, Atom, Vim, Sublime Text, TextEditor

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·

I liked Sublime Text for its speed, simplicity and keyboard shortcuts which synergize well when working on scripting languages like Ruby and JavaScript. I extended the editor with custom Python scripts that improved keyboard navigability such as autofocusing the sidebar when no files are open, or changing tab closing behavior.

But customization can only get you so far, and there were little things that I still had to use the mouse for, such as scrolling, repositioning lines on the screen, selecting the line number of a failing test stack trace from a separate plugin pane, etc. After 3 years of wearily moving my arm and hand to perform the same repetitive tasks, I decided to switch to Vim for 3 reasons:

  • your fingers literally don’t ever need to leave the keyboard home row (I had to remap the escape key though)
  • it is a reliable tool that has been around for more than 30 years and will still be around for the next 30 years
  • I wanted to "look like a hacker" by doing everything inside my terminal and by becoming a better Unix citizen

The learning curve is very steep and it took me a year to master it, but investing time to be truly comfortable with my #TextEditor was more than worth it. To me, Vim comes close to being the perfect editor and I probably won’t need to switch ever again. It feels good to ignore new editors that come out every few years, like Atom and Visual Studio Code.

12 upvotes·1 comment·35.7K views

Decision about Git, Heroku, Rails, PersonalStack, ProjectGenerator, Productivity

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·
GitGitHerokuHerokuRailsRails
#PersonalStack
#ProjectGenerator
#Productivity

Rails is great because "all the decisions are made for you", right? But I wouldn't be writing this decision if this were truly the case. ;-)

rails new and boilerplate generators are nice, but you still have to spend some time adding your favorite gems, tools, formatting files to your standards, removing unused functionality, and configuring deploys. Only after all of this can you truly begin to code.

That’s why I made a shell script (yeah, Rails generators are overkill) that creates a new app from a boilerplate app I preconfigured. Everyone has different tastes and levels of seniority, so I am not sharing this app to the public. Just know that it has different Git branches that my shell script can choose: master (default config), devise, forms, worker, etc. It comes bundled with the tools listed in my personal stack.

All I have to do is run the script, follow the README, and 2 minutes later my app is running a hello world page on Heroku! I cannot stress how powerful it is to have a professional-grade application ready and deployed in 2 minutes. It feels like I’m cheating the system. These superpowers have proved invaluable for personal projects, hackathons and professional projects alike.

Productivity ProjectGenerator PersonalStack

9 upvotes·9.5K views

Decision at StackShare about Ruby, StackDecisionsLaunch, ID

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·
RubyRuby
#StackDecisionsLaunch
#ID

For stack decisions, I needed a non-sequential ID format to prevent users from guessing other IDs. My options were:

  • UUIDs v4 that look like this: 496a52cd-49ba-4424-99d9-344e44803cb1
  • Hashids that look like this: xpAYDx0m
  • Flake IDs whose Mastodon Ruby implementation looks like this: 101151084044583231

I eventually chose flake IDs, because IMO they are better-looking and easier to type.

Although they are meant for distributed systems at scale (think Twitter), for my feature I only cared about how nice they looked. As a bonus, because the first few bits are time-based, they "feel" like good old incremental IDs. #StackDecisionsLaunch

9 upvotes·2 comments·4.9K views

Decision at Gratify Commerce about AWS Elastic Beanstalk, Heroku, Rails, PaaS

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·

When creating the web infrastructure for our start-up, I wanted to host our app on a PaaS to get started quickly.

A very popular one for Rails is Heroku, which I love for free hobby side projects, but never used professionally. On the other hand, I was very familiar with the AWS ecosystem, and since I was going to use some of its services anyways, I thought: why not go all in on it?

It turns out that Amazon offers a PaaS called AWS Elastic Beanstalk, which is basically like an “AWS Heroku”. It even comes with a similar command-line utility, called "eb”. While edge-case Rails problems are not as well documented as with Heroku, it was very satisfying to manage all our cloud services under the same AWS account. There are auto-scaling options for web and worker instances, which is a nice touch. Overall, it was reliable, and I would recommend it to anyone planning on heavily using AWS.

7 upvotes·1 comment·15.5K views

Decision about Rails, PostgreSQL, DataTypes, Lookups

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·
RailsRailsPostgreSQLPostgreSQL
#DataTypes
#Lookups

Does your PostgreSQL-backed Rails app deal with slugs, emails or usernames? Do you find yourself littering your code with things like Model.where('lower(slug) = ?', slug.downcase)?

Postgres strings are case-sensitive, but you often want to look these fields up regardless of case. So you use downcase/lower everywhere... You may refactor this inconvenience in dedicated methods like find_by_slug, but all too often your team will forget about it and use find_by(slug:, leading to inevitable bugs.

What if I told you that you could delegate all this dirty work to Postgres, thanks to the case-insensitive citext type? You can change your column type to citext like so:

class ChangeSlugsToCitext < ActiveRecord::Migration
  def change
    enable_extension('citext')
    change_column :blah, :slug, :citext
  end
end

Now, you can use find_by(slug: as you are used to, and Postgres will internally call lower on the two compared values. Problem solved!

#Lookups #DataTypes

7 upvotes·3 comments·5.6K views

Decision at StackShare about PostgreSQL, Redis, StackDecisionsLaunch, Leaderboards

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·
PostgreSQLPostgreSQLRedisRedis
#StackDecisionsLaunch
#Leaderboards

I needed to implement the "Top Contributors" feature of StackShare, that gets updated whenever someone posts a decision. I hesitated between 2 solutions for data storage:

  1. Store real time updates in a Redis sorted set. It's like having a big in-memory hash, but in Redis.

    • Pros: Best for pure real time feedback. Also, Redis sorted sets are cool!
    • Cons: Web devs may not be familiar with Redis sorted sets. Also, we still have to query our traditional DB to enrich Redis results.
  2. Add a cached_score column for the PostgreSQL records shown in the leaderboard. This column is recalculated in our app whenever a record is updated. Make that column indexable for sorting, sort the records by descending order, and voilà, you have leaderboards. Cache the result for X seconds to keep DB queries low while still keeping a more or less "real time" feel.

    • Pros: Web devs are more familiar with traditional DB sorting code.
    • Cons: Every X seconds, you still have to do a DB sort on a big table.

We ended up choosing solution 2 with PostgreSQL for a couple reasons. 1) We currently don't treat Redis as persistent storage and don't have redundancy in place, so data could disappear. 2) Up-to-the-second real time updates weren't mandatory. #Leaderboards #StackDecisionsLaunch

6 upvotes·6.3K views

Decision about Ruby, Rails, PostgreSQL, DataTypes, Hacking

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·
RubyRubyRailsRailsPostgreSQLPostgreSQL
#DataTypes
#Hacking

Sometimes I need a quick way to store a list of things, without new PostgreSQL tables and Rails associations. I just want to add a field to an existing table and call it a day. This is useful for simple features, or when the future is uncertain.

For example, you could store T-shirt sizes in a 'S,M,L,XL' string, but then you'd have to join/split when storing/reading. What if I told you that you could delegate all this dirty work to Postgres?

You can store a ['S','M','L','XL'] array with the Postgres array type:

add_column :products, :sizes, :string, array: true, default: []

When reading the value from the DB, Rails will present it to you as a Ruby array. Nice!

And if you want to store hashes like [{ 'size': 'S', 'color': 'Red' }, { 'size': 'M', 'color': 'Green' }], Postgres' jsonb type has you covered too:

add_column :products, :sizes, :jsonb, default: []

Happy #Hacking!

#DataTypes

6 upvotes·6.1K views

Decision at StackShare about Rails, Puma, Unicorn

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·

We switched from Unicorn (process model) to Puma (threaded model) to decrease the memory footprint of our Rails production web server. Memory indeed dropped from 6GB to only 1GB!

We just had to decrease our worker count and increase our thread count instead. Performance (response time and throughput) remained the same, if not slightly better. We had no thread-safety errors, which was good.

Free bonus points are:

  • Requests are blazing fast on our dev and staging environments!
  • Puma has first-class support for WebSockets, so we know for sure that Rails ActionCable or GraphQL subscriptions will work great.
  • Being on Puma makes us even more "default Rails"-compliant since it is the default Rails web server these days.
6 upvotes·2 comments·5.2K views

Decision at StackShare about Ruby, Rails, RSpec

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·

We use RSpec because it is a de-facto Rails industry standard.

minitest was an interesting alternative because it was part of the Ruby standard library, but this is not the case any more. Also, at the time of writing, the real-world-rails collection shows that it is used in only 31 Gemfiles vs 135 Gemfiles for RSpec.

RSpec works reliably well for an overwhelming majority of people who are used to it, so I guess that is why they don't see a need to change.

6 upvotes·2.6K views

Decision at StackShare about Git, Rails, RSpec, RuboCop, Brakeman, Code Climate, CircleCI, GitHub, ContinuousIntegration

Avatar of jeromedalbert
Senior Backend Engineer at StackShare ·

The continuous integration process for our Rails backend app starts by opening a GitHub pull request. This triggers a CircleCI build and some Code Climate checks.

The CircleCI build is a workflow that runs the following jobs:

  • check for security vulnerabilities with Brakeman
  • check code quality with RuboCop
  • run RSpec tests in parallel with the knapsack gem, and output test coverage reports with the simplecov gem
  • upload test coverage to Code Climate

Code Climate checks the following:

  • code quality metrics like code complexity
  • test coverage minimum thresholds

The CircleCI jobs and Code Climate checks above have corresponding GitHub status checks.

Once all the mandatory GitHub checks pass and the code+functionality have been reviewed, developers can merge their pull request into our Git master branch. Code is then ready to deploy!

#ContinuousIntegration

5 upvotes·12.6K views