How to use custom gems without changing the Gemfile
Tags: ruby, gems, rails, programming
Published: 2024-05-22 08:01:47

## Intro

_It was a typical Tuesday. My warm coffee sat on the table, and my rubber duck was in front of me. I remembered that last week I had been investigating a bug and knew which method I needed to look into for troubleshooting. There was something wrong with one of the arguments._

_I updated my branch, ran `bundle install`, and started the server. I put `binding.pry` in that method to check the argument. Sure enough, the argument wasn't supposed to reach the method I was investigating. I needed to find out who was calling this method and how the argument was being built. In the pry debug console, I typed `up` and suddenly got an `undefined method "up"` error._

_Did I make a typo? No. But there had been some gem updates - maybe my favorite `pry-byebug` gem had major changes? I opened the `Gemfile`, and it was gone! I found a commit with the description "Do not use `pry-byebug` because it slows down the app." You know what - I'll take a slower app if it allows me to develop faster!_

I’m sure you have your own stories about how certain development gems are considered a disadvantage for the project, even though they help you work more efficiently.

Well, I have good news for you - you can still use any gem you want in your development environment without changing the project codebase.

### Gemfile.personal technique

The cleanest solution I've found is to use a separate `Gemfile.personal` and a custom `Gemfile` path. This way, you can use it in any project without modifying the project code at all.

#### 1. Add the `Gemfile.personal` to the project's root directory

```ruby
# /path/to/your_ruby_project/Gemfile.personal
eval File.read('Gemfile') # use all gems from Gemfile

gem 'personal-gem1'
gem 'personal-gem2'
```

#### 2. Install gems using the `Gemfile.personal` file

When installing gems, use the `--gemfile` option:

```sh
bundle install --gemfile=Gemfile.personal
```

To keep `Gemfile.personal.lock` synchronized with `Gemfile.lock`, copy the contents of `Gemfile.lock` to `Gemfile.personal.lock` whenever you update your personal gems. Use the following script:

```sh
cp Gemfile.lock Gemfile.personal.lock && \
bundle install --gemfile=Gemfile.personal
```

#### 3. Globally ignore `Gemfile.personal` and `Gemfile.personal.lock` 

```sh
touch ~/.gitignore
echo "Gemfile.personal\nGemfile.personal.lock" >> ~/.gitignore
git config --global core.excludesFile '~/.gitignore'
```

This will apply to all projects, so you don't need to update each project's `.gitignore` separately.

**4. Update the `BUNDLE_GEMFILE` environment variable

If you want to use your custom Gemfile occasionally, you can include `BUNDLE_GEMFILE=Gemfile.personal` before every command, like this:

```sh
BUNDLE_GEMFILE=Gemfile.personal bundle exec rails console
```

But I find that annoying. Instead, I use bash/zshell aliases to make my life easier:

```sh
# ~/.bashrc
alias be="bundle exec"

# The letter "c" stands for "custom"
alias bec="BUNDLE_GEMFILE=Gemfile.personal be"
```

Now, I can switch Gemfiles by adding or removing one letter:

```sh
be rails console # uses the default Gemfile
bec rails console # uses Gemfile.personal
```

However, this option is not for everyone. If you want to always use your custom `Gemfile.personal`, you could also set this value globally by adding this line at the end of your `~/.bashrc` or `~/.zshrc` file:

```sh
# ~/.bashrc or ~/.zshrc
export BUNDLE_GEMFILE=Gemfile.personal
```

You could use a `.env` file to expose this variable per project:
```sh
# /path/to/your/project/.env
BUNDLE_GEMFILE=Gemfile.personal
```

##Final Thoughts

Using the `Gemfile.personal` technique allows you to customize your development environment without affecting the rest of the team. It’s a flexible solution that keeps the project’s codebase unchanged while giving you the tools you need to work efficiently. With a few simple steps, you can set up your environment to include your preferred gems, making debugging and development smoother and faster. This approach ensures that your workflow remains uninterrupted and tailored to your preferences, all without impacting the project's performance or stability. Happy hacking!