Rails app object in console versus in scripts - ruby-on-rails

I'm trying to use the app object inside a Ruby script that loads the Rails environment but I have only problems...
Script looks like this:
ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
require ::File.expand_path('../config/environment', __FILE__)
app = Rails.application
puts app.users_path(21)
I get
undefined method `users_path' for #<BacklinkHealth::Application:0x007fd6fac80d60> (NoMethodError)
If I include Rails.application.routes.url_helpers then it's ok...
but the problem is that I also need to call app.get and I don't know how to enable that.
Why is this app object so different in a script than it is in Rails command line?

I see that app is a method in console and it returns an instance of ActionDispatch::Integration::Session while Rails.application is BacklinkHealth::Application. So the solution is:
app = ActionDispatch::Integration::Session.new(Rails.application)

Related

Getting uninitialized constant from Sidekiq worker

I'm missing something, just not sure what. Sidekiq is up and running fine, I can see it in my terminal.
I have this worker, defined in app/workers/sqs_worker.rb
class SqsWorker
include Sidekiq::Worker
require 'aws-sdk'
def perform
#do something
end
end
And then in just a test file at app/test.rb I have the very simple code:
require 'sidekiq'
SqsWorker.new.perform_async
When I run the test.rb file I get this error: uninitialized constant SqsWorker (NameError)
Where did I go astray? I'm running Sidekiq (4.1.4)
I tried killing the running processes and restarting both Sidekiq and Redis to no luck.
uninitialized constant SqsWorker (NameError) indicates that your script in test.rb is not able to locate class SqsWorker
All you need to do is replace require 'sidekiq' with require_relative 'workers/sqs_worker' to make your script aware about location of SqsWorker class.
Probably, you ran the test.rb from outside of the scope of the application with something like that:
ruby app/test.rb
But for this purpose, You need to add to your test something like this:
require 'rubygems'
require 'bundler/setup'
require File.expand_path('../config/environment', __FILE__)
SqsWorker.new.perform_async
And run as this:
bundle exec ruby app/test.rb
Why do you need this? Because nowadays, the bundler manages your dependencies added to your app and therefore, you need to load the rails environment too and the last will load all the things under app/ basically.

rails 4: Rails.env is different from ENV["RAILS_ENV"]

I set in my config/environment.rb file ENV["RAILS_ENV"] = "production" in order to run my server on my machine (using rails server) and get the production behavior. I have a lot of lines in my code that check if Rails.env.production? to assign a different functionality for some of the app components.
My problem is that when I check the environment in one of my controller I get different results for Rails.env and ENV["RAILS_ENV"]. The first will show "development" while the second will be "production".
Shouldn't both of the methods return the same value?
By the time config/environment.rb is evaluated you're just modifying the ENV hash. If you want to run your app in production set the RAILS_ENV environment variable in the shell you use to run rails.
RAILS_ENV=production bundle exec rails c
To run your rails server in production mode run :
rails s -e production
And to answer your actual question :
Rails.env uses ENV["RAILS_ENV"] internally, see :
https://github.com/rails/rails/blob/d25fe31c40928712b5e08fe0afb567c3bc88eddf/railties/lib/rails.rb#L59-L61
def env
#_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
end
but ENV["RAILS_ENV"] which is actually not set till now, so the option that is passed with -e if passed while the rails server command is triggered comes into picture, see:
https://github.com/rails/rails/blob/3e36db4406beea32772b1db1e9a16cc1e8aea14c/railties/lib/rails/commands/server.rb#L62-64
def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end
for environment option see:
https://github.com/rails/rails/blob/3e36db4406beea32772b1db1e9a16cc1e8aea14c/railties/lib/rails/commands/server.rb#L31
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |v| options[:environment] = v }
and all this is happening before your applications environment.rb is executed.
Hope this helps.

Rails: Where to put script/function that runs only when starting server?

I am using the Predictor gem for a recommendation system. I want to write a script to initialize the recommender when running rails server. If I put the script into the initializers/dirctory, it will also be run whenever rake is executed.
Is there a way to add scripts are executed only when running rails server?
Thought it is not recommended, you could update the file bin/rails:
#!/usr/bin/env ruby
puts "Write your custom code here"
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
This runs whenever rails s, rails c or any rails command is called.

How to run my ruby code after Rails server start?

I tried:
after_initialize do
#code
end
But: (documentation)
Some parts of your application, notably observers and routing, are not
yet set up at the point where the after_initialize block is called.
I need routing and logger in my code
Any ideas?
See section 3.1 from http://guides.rubyonrails.org/configuring.html
I believe you would put this code in config/application.rb
config.after_initialize do
# ....
end
# config.after_initialize takes a block which will be run after Rails has finished initializing the application.
# That includes the initialization of the framework itself
Also http://guides.rubyonrails.org/initialization.html
#house9's answer is correct, as pointed out by the comments, this will also execute when running rake tasks, console, etc. I used the following to recognize when a server was actually being executed:
# application.rb
if defined?(Rails::Server)
config.after_initialize do
# Do stuff here
end
end
Another option is to create a custom initializer. It's just a ruby file that lives under config/initializers/ and is executed exactly "on_server_start" event :)
Lines added to config.ru will be run by the Rails server, but not by Rails console or Rake tasks that load the environment.
# config.ru
# This file is used by Rack-based servers to start the application.
require ::File.expand_path("../config/environment", __FILE__)
# your code here (after environment is loaded)
run Rails.application
Since Rails 5 the default server is Puma, so code in config/puma.rb will be run just once, and only if the server is started.

Rails script access model

i need a script to be able to access my model. I found a post about this which suggested doing
require "#{ENV['RAILS.root']}/config/environment.rb"
in the top of my script. then i can run ruby script/my_script.rb to run it. But this gives me the error
/Users/my_name/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': no such file to load -- /config/environment.rb (LoadError)
what am i doing wrong
I think ENV['RAILS.root'] will be set after the environment is loaded. You can try
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
However, a more commonly used idiom is writing Rake task. For example, create a file named lib/tasks/mytask.rake:
task :mytask => :environment do
# Do something with your model
end
Then execute rake mytask. The environment task will automatically load the Rails environment.
I found my own answer. forget what i said to include in the top. put this instead
ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")

Resources