Why does if __FILE__ == $0 not work on Heroku with Rails 5.2?

Viewed 142

I previously had some scripts of this form:

class Thing
  def do_things
    ...
  end
end

if __FILE__ == $0
  Thing.new.do_things
end

I invoked them with rails runner. They were working well on Heroku with Rails 5.1. When I upgraded to rails 5.2, they no longer ran on Heroku (silently exiting with the block not being executed). But they do still execute in my dev environment (Ubuntu).

I run them using the relative path to the script (e.g. rails runner scripts/thing.rb)

Rails 5.2

Heroku

  • __FILE__: the absolute path to the script (/app/scripts/thing.rb)
  • $0: the filename (thing.rb)

Dev Environment (ubuntu)

Both contain just the filename.

Rails 5.1

In both environments, both contain just the filename.

1 Answers

My team ran into this problem when upgrading our app to Rails 5.2 too. We don't use Heroku, so this is an issue with Rails in general instead of Heroku.

When running any Ruby file with rails runner, we found that __FILE would use an absolute path if ENV["RAILS_ENV"] was set to "test" or "production", but use a relative path if set to "development" or was unset. Interestingly enough, if the environment was set with the -e flag instead, then __FILE__ would always use a relative path.

We discovered that removing bootsnap as a dependency fixed the issue for us. It also means you would have to remove the require "bootsnap/setup" line from config/boot.rb.

It looks like there may be a bug with regards to how Rails and Bootsnap are both reading environment variables and somehow overwriting how Ruby sets __FILE__. Feel free to track this issue: https://github.com/rails/rails/issues/36550

Related