Rails - execute rake tasks at startup - ruby-on-rails

I have the following code in config/application.rb
config.after_initialize do
IndividualProject::Application.load_tasks
#load File.join(Rails.root, 'lib', 'tasks', 'download_csv.rake')
Rake::Task[ 'download_csv:get_files' ].invoke
Rake::Task[ 'download_csv:place_in_database' ].invoke
end
My problem is that if I try to execute migrations, I get a database error which says that one of tables I'm referencing in the rake task does not exist.
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "currencies" does not exist
I can solve the issue by commenting out the code and then running the migrations. After this, the server runs fine.
However, I want to deploy to Heroku, where I can't comment out the code before running the migrations.
How should I solve this issue?
Do I need to place the code somewhere else in the project?

Remove your code from config/application.rb and change the web process in Procfile like following:
web: rake download_csv:get_files && rake download_csv:place_in_database && bundle exec rails server -p $PORT
Change bundle exec rails server -p $PORT with whatever code you use to start your server.
If you don't have Procfile in your project yet, create one and add it to git.
Now your rake tasks will be executed only before starting the server.

Related

Delayed Job in Rails 4 with Capistrano

I cant figure how to start Delayed Jobs on a dedicated Ubuntu server.
It works fine on my localhost but when I run on my server
sudo RAILS_ENV=production bin/delayed_job restart
I get
sudo: bin/delayed_job: command not found
On top of that, if I run the "rake jobs:work RAILS_ENV=production" command Im getting the following error:
PG::FeatureNotSupported: ERROR: SELECT FOR UPDATE/SHARE is not allowed in subqueries
Apparently theres an issue with my psql version.
Is there any way I can get the script to work? Any effective Capistrano recipes available? All ive found on the web are old recipes for Rails 3 and older versions of capistrano.
Thanks in advance.
EDIT:
I have already bundled install the daemons gem and generated "delayed_job:active_record" on my local machine, then proceded to cap deploy which bundle installed and migrated in the production server.
The bin/delayed_job file exists in the server yet it fails with command not found.
And add this to config/environment.rb:
ENV['RAILS_ENV'] ||= 'production'
Then at your production server:
RAILS_ENV=production rake db:migrate
RAILS_ENV=test production generate delayed_job:active_record && RAILS_ENV=production rake db:migrate
Now after you do that:
RAILS_ENV=production script/delayed_job start
As for Capistrano error you are facing, please try to add the command like:
run "cd #{current_path}; #{sudo} RACK_ENV=production bundle exec #{current_path}/bin/delayed_job start"
You must run this on target server:
bundle exec rails generate delayed_job

Resque workers do not start due to middleware failure

I have rescue 1.22.0 installed locally and on a server. To be able to catch MultiJson::DecodeErrors I added the following to my application.rb:
config.middleware.swap ActionDispatch::ParamsParser, ::MyParamsParser
and added the class to my lib folder. In dev mode this works fine, I can rescue from DecodeErrors and I can start a worker using:
QUEUE=* bundle exec rake environment resque:work
In production mode on my server the code itself works as well, but my god process was not able to start workers again. The error that occurs after god starts a worker:
QUEUE=* /usr/local/rvm/rubies/ruby-1.9.2-p320/bin/ruby /usr/local/rvm/gems/ruby-1.9.2-p320#global/bin/bundle exec rake -f /home/deployer/apps/kassomat/current/Rakefile environment resque:work
rake aborted!
No such middleware to insert before: ActionDispatch::ParamsParser
I tried to patch my application.rb
config.middleware.swap ActionDispatch::ParamsParser, ::MyParamsParser if Object.const_defined?('ActionDispatch') && ActionDispatch.const_defined?('ParamsParser')
but that did not work out. I do not understand why this works in development but fails in production.
Can anyone help?
Regards
Felix

Automatically Starting ElasticSearch with Rails

I've been doing Ruby on Rails development with ElasticSearch between two machines and its starting to get a little annoying. My usual workflow is:
git pull
bundle install
rake db:migrate (or rake db:setup depending)
rails server
elasticsearch -f -D myconfig.xml
rake environment tire:import CLASS=MyObject FORCE=true
Is there anyway I can add all of these commands to some type of start up script in Rails to bring them all into one place? It would make bringing up a dev environment a lot easier on me everytime I switch machines.
The best way I've found is to use the Foreman gem to kickstart your project and associated processes.
It looks like you should do this in your deployment using Capistrano. Here is an example config/deploy.rb file:
[basic parts omitted]
after "deploy", "bundler:bundle_install"
after "bundler:bundle_install", "db:db_migrate"
after "deploy:db_migrate", "deploy:elastic_search_indexing"
namespace :bundler do
desc 'call bundle install'
task :bundle_install do
run "cd #{deploy_to}/current && bundle install"
end
end
namespace :db do
desc 'fire the db migrations'
task :db_migrate do
run "cd #{deploy_to}/current && bundle exec rake db:migrate RAILS_ENV=\"production\""
end
end
namespace :elasticsearch do
desc 'run elasticsearch indexing via tire'
task :index_classes do
run "cd #{deploy_to}/current && bundle exec rake environment tire:import CLASS=YourObject FORCE=true "
end
end
[rest omitted]
Make sure you have a config file on the target machine (Linux) in /etc/elasticsearch/elasticsearch.yml with contents like:
cluster:
name: elasticsearch_server
network:
host: 66.98.23.12
And the last point to mention is that you should create an initializer config/initializers/tire.rb:
if Rails.env == 'production'
Tire.configure do
url "http://66.98.23.12:9200"
end
end
As you can see, this is the exact same IP address, but only used for the production environment. I assume that you access elasticsearch locally (in development mode) via localhost. elasticsearch is connection per default to
http://0.0.0.0:9200
A good starting point and also in depth help is provided by awesome Ryan Bates and his Railscasts http://railscasts.com/episodes?utf8=%E2%9C%93&search=capistrano
Whats keeping you from putting it in a bash script? And put the script inside your RAILS_APP_HOME/scripts folder?
#!/bin/sh
git pull
bundle install
rake db:migrate
rails server
elasticsearch -f -D myconfig.xml
rake environment tire:import CLASS=MyObject FORCE=true

Rake error fixed by bundle exec, but deployment not working

I pushed an update to my Rails app production server, and in the update there was a new database migration. I ran rake db:migrate and got the common error seen here. I ran the rake again in bundle exec bash and it was successful. But after restarting my apache server, I'm now getting the 500 Error page. This update worked fine on my localhost, and was mostly this update to the db with supporting changes in the according view and controller/routing.
I don't even know why this error appeared this time, as I have pushed db updates successfully before using only rake. Nonetheless, the rake was successful. The 500 error page only shows on pages that require that specific new ActiveRecord. Any ideas on how to debug?
EDIT: My problem was an extremely simple one. I merely forgot to include the environment with the rake:
bundle exec rake db:migrate RAILS_ENV=production
Unfortunately, it took quite a while to narrow that down, as I couldn't use IRB to check the db entries until I followed these steps.
Did you run rake db:migrate on your server? Also be sure to set the RAILS_ENV flag so your production database is updated:
rake db:migrate RAILS_ENV=production

Running rake db:migrate without some initializers

I am trying to run jruby -S rake db:migrate, but I do not want to start up a daemon in config/initializers whenever I do a migrate. Is there a way to do this? Up until now, I have just been moving the daemon file to a file with a .bak extension so that rails doesn't load it when I do the migrate.
I suspect that this is a stupid way of doing things. Is there a better way?
Oh and I am running jruby ( if it matters ).
When run:
NODAEMON=1 rake db:migrate
In initializer:
unless ENV['NODAEMON']
# ...
end
You can also create separate task for setting NODAEMON, e.g.
task :fast_migrate do
ENV['NODAEMON'] = '1' # or just set global variable, or some config
Rake['db:migrate'].invoke
end

Resources