Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A better way to check if Rails was run from console #323

Closed
PhilT opened this issue Jul 28, 2021 · 16 comments
Closed

A better way to check if Rails was run from console #323

PhilT opened this issue Jul 28, 2021 · 16 comments
Assignees

Comments

@PhilT
Copy link

PhilT commented Jul 28, 2021

return if defined?(Rails::Console) || Rails.env.test? || File.split($0).last == 'rake' didn't work too well for me and is also quite wrong in that defined? returns a string not a boolean. Yuck.

After quite a bit of digging I found the Ruby 2.5 class method const_defined? to be more suitable. Rails.const_defined?('Console') did the trick and correctly returned when in an initializer.

I hope this helps others.

@PhilT
Copy link
Author

PhilT commented Jul 28, 2021

Also when run in an initializer there is no method and therefore it does not return. This also handles multi-process servers such as Puma. So I found this structure to be more useful:

  dont_run_scheduler = Rails.const_defined?('Console') || Rails.env.test? || File.split($PROGRAM_NAME).last == 'rake'                                                                                                                                                                                                                                                                                                                                                                                           
  schedule = Rufus::Scheduler.new(lockfile: Rails.root.join('.rufus-scheduler.lock')) unless dont_run_scheduler                                                                                                                                                                                                                                                                                                                                                                                                                          
  if schedule&.up?
    ...
  end

@jmettraux jmettraux self-assigned this Jul 28, 2021
@jmettraux
Copy link
Owner

Hello,

and is also quite wrong in that defined? returns a string not a boolean. Yuck.

There is nothing wrong with that, truthy and falsey are good enough and it reads well. Keep your "Yuck" for yourself.

Also when run in an initializer there is no method and therefore it does not return.

What method are you talking about?

May I get a decent issue report?

Thanks in advance and best regards.

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

Sorry it's not really an issue. Just a minor point with the example code that it uses return but the initializer is not in a method.

My main point with is issue is that
defined?(Rails::Console) didn't work for me but Rails.const_defined? did

@jmettraux
Copy link
Owner

Thanks.

defined?(Rails::Console) used to work, at least when I wrote that part of the readme.

What version of Rails are you using on what version of Ruby?

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

Yeah it's possibly version related. I'm using Rails 6.1.4, Ruby 2.6.6. I'll give it a try on a 5.2 app I've as well.

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

My mistake. return is working. I must have been conflating issues. So ignore that part of it.

So yeah, in Rails 6 Rails::Console is not defined in the initializer but Rails.const_defined?('Console') does work so it must lazy load it. defined?(Rails::Console) does work once you're in the console.

defined?(Rails::Console) works fine in Rails 5 so seems to be a Rails 6 change.

@jmettraux
Copy link
Owner

Thanks a lot!

I will adapt the README to that change.

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

Hold on, I'm having trouble with Rails.const_defined?('Console') now. I'll do some more testing and get back to you.

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

I'm at a loss. Rails::Console does not appear to be defined at the point the initializers are called in Rails 6. Which is weird as the args have been consumed at that point.

However, when running in a console the scheduled jobs are not run, I'm guessing because the console is blocking. So it seems a little accidental but has the same effect. There maybe other scenarios where they do run however.

@jmettraux
Copy link
Owner

OK, I will take a look at that during the week-end. Thanks for the information so far!

@PhilT
Copy link
Author

PhilT commented Jul 29, 2021

Thanks. And thank you for a great tool!

@jmettraux
Copy link
Owner

notes in passing, while playing with a test Rails 6 install

@jmettraux
Copy link
Owner

Hello,

I am not a Rails user, but I can find my way around.

I think that the Spring tool is what is giving you sketchy result. When Spring is in action, the Rails initializers are run only once (and they stick in the Spring process). You have to run spring stop to force the initializers being re-run.

I disabled Spring with export DISABLE_SPRING=true && spring stop and the "guard" code at the top of the initializers got evaluated (and prevented the scheduler running) each time rails c got called.

Could you please double check that on your side? If that's the case, I'll update the rufus-scheduler README to explain the situation.

Thanks in advance.

@PhilT
Copy link
Author

PhilT commented Aug 1, 2021

Yeah I was doing spring stop each time as I want it to work with Spring as well. The other thing is that even if you exit the console, if Spring is still running it'll keep running scheduled jobs.

It also is running when in the console. It wasn't logging to screen but I checked the Rails logger and it's still pumping messages into there when the jobs run.

I'm thinking it might not be useful to run in development anyway so I'll probably have a flag you can set to turn it on. Normal behaviour is for people to run Spring and I don't want to force them to do something different.

I think a note about Spring would be useful.

Thanks so much for looking into this.

@PhilT
Copy link
Author

PhilT commented Aug 1, 2021

Just to clarify: If you run a console with Spring then exit the console jobs will still run until running spring stop. This doesn't happen when running the server however.

@jmettraux
Copy link
Owner

OK.

Yesterday I worked with https://github.com/jmettraux/sc_gh323_rails_console

  • Rails 6.1.4
  • ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-openbsd6.7]
  • OpenBSD yawara 6.9 GENERIC.MP#3 amd64

Once Spring was put aside, all the rails c console calls were correctly skipped, as per my original console detection code. I experienced no cases of rails c not skipping the scheduler initializer.

I cannot reproduce your issue. I will add a note about Spring in the README and then close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants