How to run a model method in capistrano deploy - ruby-on-rails

Suppose I have a model method
def self.do_something
How do I run this method after deploy in capistrano? I've tried runner, I've tried making a rake task, nothing works. Can someone provide an exemplar?
Thanks,
kevin

You have to load the rails environment before calling your rake task in your deploy file, Capistrano doesn't do it.
run "cd #{current_path} ; RAILS_ENV=#{rails_env} bundle exec rake my:task"

Related

How can I run a rake task via cron?

I have and rails application and a rake task which I'm going to execute by cron around once in an hour. But the thing is that the task uses rails environment and some classes of my rails application. If I run it as ruby script, I'll have to include all the dependencies it uses and I think it's not possible to do it correctly and in a simple way. So I'll have to run it as a rake task because it'll preserve all the dependencies, right? Then how can I run a rake task from cron?
Note that I prefer not to use any third-party solution when there's no necessity, in this case I don't want to use the gem whenever or the like.
You can add to your crontab something like
0 * * * * /bin/bash -l -c 'cd /path/to/your/project && bundle exec rake foo:bar >> log/cron.log 2>&1'
This will run foo:bar task every hour and write stdout and stderr to log/cron.log.
Please notice bundle exec before rake command.
Using bundler ensure you that task will fetch correct environment.
To specify RAILS_ENV you can do
... && RAILS_ENV=production bundle exec rake foo:bar
Use whenever to simplify your life https://github.com/javan/whenever ;)
Here's an example of a rake task:
task :foo => :environment do
puts "Running rake task in environment: #{Rails.env}"
# can access Models here or whatever
end
Note that the => :environment part is optional, but it what makes your Rails environment to the task block.
You can put rake run_my_task in your cron job.
You may need to use something like cd /home/$USER/my_rails app && rake run_my_task to ensure that the cron runs the task from the Rails root directory.

Rails deployment - how do you do rake db:reset with capistrano?

I am using Linode with Ubuntu 10.04 and Capistrano, Unicorn, & Nginx to deploy.
How do I do the equivalent of heroku run rake db:reset with this setup? Is it as simple as cap deploy:cold again to run the migrations?
I've already deployed and want to drop all databases and rerun all the migrations but am not sure which commands to run with this setup to do so.
I wrote a tiny little file you can copy to run arbitrary rake tasks via capistrano: http://jessewolgamott.com/blog/2012/09/10/the-one-where-you-run-rake-commands-with-capistrano/
once setup, you can:
cap sake:invoke task="db:reset"
For Capistrano 3 without actual dropping the database. Use bundle exec cap db:reset
namespace :db do
desc 'Resets DB without create/drop'
task :reset do
on primary :db do
within release_path do
with rails_env: fetch(:stage) do
execute :rake, 'db:schema:load'
execute :rake, 'db:seed'
end
end
end
end
end
You could add the following to your deploy.rb file
namespace :custom do
task :task do
run "cd #{current_path} && bundle exec rake db:reset RAILS_ENV=#{rails_env}"
end
end
Then run cap custom:task to clear the database.
If you are using Capistrano 3, consider using the capistrano-rails-collection.
You can also use copy the code directly from db.rake file from the repository.
Or, if you want a full-fledged solution to run all your rake tasks on a remote server, check out the Cape gem.

Missing required gems when execute cron created by whenever gem in production environment

I've ruby on rails application running in production, this apps have STOCK model and it should be updated every 1 minute.
For updating this model i create simple rake task db:populate:stocks, when it contain only two operation :
truncate the STOCK model
fill STOCK model with latest data fetch from webservice
this rake task should be execute every 1 minute, for this purpose i use whenever gem. Here my schedule.rb :
env :PATH, ENV['PATH']
set :job_template, nil
set :output, {:standard => '/home/admin/shared/log/cron.log', :error => '/home/admin/shared/log/cron-error.log'}
job_type :rake, "cd :path && rake :task RAILS_ENV=:environment --trace :output"
every 1.minute do
rake "db:populate:stocks"
end
In production i'm using rvm running ruby 1.9.2-p180, rails 3.1.0 and capistrano, here my capistrano task for update cron tab :
after "deploy:update_code" do
run "cd #{release_path} && whenever --clear-crontab RAILS_ENV=production"
run "cd #{release_path} && whenever --update-crontab RAILS_ENV=production"
end
And my schedule.rb create cron task like :
# Begin Whenever generated tasks for: RAILS_ENV=production
PATH=/home/admin/.rvm//gems/ruby-1.9.2-p180#admin/bin:/home/admin/.rvm//gems/ruby-1.9.2-p180#global/bin:/home/admin/.rvm//rubies/ruby-1.9.2-p180/bin:/home/admin/.rvm//bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
* * * * * cd /home/admin/releases/20120904103658 && RAILS_ENV=production rake db:populate:stocks --trace >> /home/admin/shared/log/cron.log 2>> /home/admin/shared/log/cron-error.log
THE PROBLEM is the cron task failed to execute the rake task, from cron-error.log :
/home/admin/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems.rb:314:in `bin_path': can't find gem rake ([">= 0"]) with executable rake (Gem::GemNotFoundException)
from /home/admin/.rvm//gems/ruby-1.9.2-p180#admin/bin/rake:19:in `<main>'
What i'm missing here, why the cron job failed to load my env ? Is there any problem with my schedule.rb ?
Make sure your RVM defaults to the correct ruby version where the gems are.
Then try to use bundle exec rake ...
by doing so it will explicitly invoke whatever the gems in the bundle (assuming you are using RVM)
I have similar problem and I fix with
rvm cron setup
in server. This add rvm env variables (PATH, GEM_HOME,GEM_PATH...) to my cronjob.
I have to delete the set command
env :PATH, ENV['PATH']
modifying PATH is not enough, check rvm help cron - there are few options that will help manage rvm in crontab.

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

Can I interact with Rails models within a Capistrano task?

I often used Rake tasks that are dependent upon the Rails environment task having loaded. I then interact with Rails Models within the Rake tasks. Can I do this in Capistrano?
You can definately use capistrano to fire a rake task.
desc 'Run a Rake Task.'
task :after_deploy, :roles => :app do
run "cd /path/to/app && rake -e environnment task here"
end
If you are asking if you can access a rails model from Capistrano, then I would say I don't think so unless you are using some other way that also loads a rails environment, like script/runner.
I'd say stick with firing a rake task from Capistrano.
The below might be better:
run "cd #{current_path} && #{rake} RAILS_ENV=#{rails_env} sunspot:solr:stop"

Resources