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
Related
I'm running a small demo site. I'd like to reset the database once an hour or so (automatically, not manually). I could write a rake task to destroy records for each of the models. Is there a simpler approach?
How best to accomplish this?
You can use Heroku Scheduler to schedule a rake task. If you rake task runs with heroku run then it works with scheduler too.
Please refer this link to how to automate rake task on heroku
http://kakimotonline.com/2014/04/27/using-rake-to-automate-heroku-tasks/
Your rake file will look something like this:
namespace :heroku do
def run_command(cmd, app_name)
Bundler.with_clean_env do
sh build_command(cmd, app_name)
end
end
def build_command(cmd, app_name)
"heroku #{cmd} --app #{app_name}"
end
end
Following the example linked by Akshay, I was able to get this working, although not exactly as I planned.
First, a clarification. To add the scheduler add-on on Heroku, you have to provide your credit card number. I'm still getting my bearings with the Heroku platform and am not ready to do that quite yet. So my solution works without the scheduler add-on. Instead it runs as a rake task from your local dev environment and uses the heroku toolbelt to run the reset command on your remote app.
If you are looking to run everything on Heroku, I don't think this will work as you can't run the heroku pg:reset command on Heroku itself. However, it looks like this solution here would work.
Now to my solution.
First, create the following rake file:
# lib/tasks/heroku.rake
namespace :heroku do
# bundle exec rake heroku:reset_db['my-app-name']
# Note: run locally with Heroku toolbelt to reset DB on app
desc 'Reset database with seed data'
task :reset_db, [:app_name] do |t, args|
run_command("pg:reset DATABASE_URL --confirm #{args.app_name}", args.app_name)
run_command("run rake db:migrate", args.app_name)
run_command("run rake db:seed", args.app_name)
end
# Helper Functions
# Source: http://kakimotonline.com/2014/04/27/using-rake-to-automate-heroku-tasks/
def run_command(cmd, app_name)
Bundler.with_clean_env do
sh build_command(cmd, app_name)
end
end
def run_command_with_output(cmd, app_name)
Bundler.with_clean_env do
`#{build_command(cmd, app_name)}`
end.gsub("\n", "")
end
def build_command(cmd, app_name)
"heroku #{cmd} --app #{app_name}"
end
end
Now you can reset your database by running the following rake command from your local environment with your app name (run heroku apps for your app name):
bundle exec rake heroku:reset_db['my-app-name']
And if you want to schedule it to run at regular intervals as I did, add a job to your local crontab (which is a little more complicated than just copying the line above):
# Reset Heroku database hourly
RBENV_SHIM=/home/klenwell/.rbenv/shims/
RBENV_BIN=/home/klenwell/.rbenv/bin
RAILS_APP=/home/klenwell/projects/my-app-name
HEROKU_LOG=/tmp/heroku-cron.log
0 * * * * export PATH=$RBENV_SHIM:$RBENV_BIN:$PATH; eval "$(rbenv init -)"; cd $RAILS_APP && bundle exec rake heroku:reset_db['my-app-name'] >> $HEROKU_LOG 2>&1
For more info on setting up a cron job to run a rake task with rbenv, see this article.
rake db:schema:load accomplishes what you want, though I've never tried running it on Heroku.
You could also try the database_cleaner gem, which is typically used in test environments.
Try heroku run rake db:setup.
But you will have to run it manually anytime you need to.
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.
Im scratching my head here wondering if I'm barking up the wrong tree. I have a server which I've deployed a Rails app onto using Capistrano. Recently I added a new data type to one of the models, and now I need to run a Rake task to update the existing records.
After a lot of Googling I'm starting to wonder if people use Rake tasks with Capistrano. Some forum posts from 2013 or so mention that Capistrano supports the .rake extension. Whereas other posts I've found indicate that Capistrano has its own task automation system, and is incompatible with rake.
I found Cape, but I'm unsure if this is what I'm looking for as it seems to convert Rake tasks into cap recipes. Its possible I'm mistaken on this point, I really don't have any experience working with Capistrano or even working in the full stack spectrum.
What I'm wondering is this: How do I run a simple Rake task on my remote server?
Some quick points for clarity, I've installed the app on the latest Ubuntu LTS, 14.10 if memory serves. I followed the tutorial found here. I have full sudo access and I can ssh into the server.
thanks in advance for helping a noob
If you need to update models, you can of course write a Rails migration - this will ensure that it's run if it hasn't been run yet.
The easiest way to execute a rake task on the server would be just via ssh if it's a one-time task. See the last paragraph in the tutorial you mentioned:
cd /opt/www/testapp/current ; bin/rake RAILS_ENV=production db:seed
To answer your original question about rake: you can execute rake tasks via capistrano similar to how you would execute it locally, only within the capistrano script. Here's an example:
deploy.rb:
namespace :rake do
desc "My task"
task :my_task do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, "my_task"
# !!!see NOTE at end of answer!!!
end
end
end
end
end
You can view all your cap tasks via cap -T locally. The capistrano task I wrote above should show up as cap tasks:my_rake_task.
If you want to be ably to run any available rake task without configuring, do the following:
namespace :rake do
desc "Invoke rake task"
task :invoke do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, ENV['task']
# !!!see NOTE at end of answer!!!
end
end
end
end
end
Then you can write:
cap production deploy:invoke task=my:rake:task
NOTE: you might want to replace the execution line with
run "bin/rake RAILS_ENV=#{rails_env} #{ENV['task']}"
to use the same syntax as the tutorial (without the binstubs you might need to configure capistrano/bundler and capistrano/rbenv first ...)
Check out capistrano-rake
Once installed, run any rake task on your production/staging servers without messy capistrano recipes by simply doing this:
$ cap production invoke:rake TASK=your:rake:task
Full Disclosure: I wrote it
rake --tasks takes about 18s to run. This is just the time it takes to load all the tasks, as a result any task I define will take at least this amount of time to run :
$time rake --tasks
rake db:clean # Cleaning up database
rake passenger:restart # Restart Application
rake spec # Run specs
real 0m18.816s
user 0m7.306s
sys 0m5.665s
My Rakefile :
$: << "."
require "rubygems"
require "rspec/core/rake_task"
desc "Run those specs"
task :spec do
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w{--colour --format progress}
t.pattern = 'spec/*_spec.rb'
end
end
task :default => :spec
Any idea why rake takes to much times ?
Thanks
Try spring
Command line will look like:
spring rake -T
It will take more time running the first time, but subsequent runs will be very fast.
This solution worked for me: Faster rake tasks in Rails.
I had to do a little variation where I created a lib/tasks/no_rails directory and put all the Rake files which do not need Rails in there and loaded only those using the above method.
I like the solution Pratik mentions for the general case of loading rails for tasks that need it and not for those that don't, for any rake task without having to remember beforehand.
A less-invasive method to run a rake task that doesn't need rails is to use the -f rake option to tell rake to use a particular Rakefile. This way, rake won't go looking for rake tasks in all of rails.
For example, assuming your task above is in a file called Rakefile at the top level of your project and your Rakefile doesn't do anything that loads Rails like require File.expand_path('../config/application', __FILE__), you can do:
$ rake -f Rakefile spec
and it should run your spec task much faster. Try $ time rake -f Rakefile -T; I did this with a rails-independent Rakefile of mine and got:
real 0m1.543s
user 0m1.308s
sys 0m0.201s
The downside is you have to remember to specify this option every time, and not to specify it if you want to run a rake task from rails like rake db:migrate.
The entire rails environment has to be loaded, therefore even simple rake tasks such as rake --tasks take a while. Opening a console with rails console or script/console takes a similar time. You may try to hack Ruby or Rails to speed up rake, but too much optimization can be bad if you want to switch to a newer version later. Since the rails environment must be loaded, cleaning up routes may also help.
Eventually I would like to get to setting it up as a Rake task and do a cron job, but for right now...all I want to do is take my ruby script that used to work as a standalone script and have it work within my Rails app.
I renamed the file to be .rake instead of .rb and tried doing rake my_script at the command-line, but that gave me this error message:
rake aborted!
Don't know how to build task 'my_script'
(See full trace by running task with --trace)
How do I run this script within my Rails environment?
This is the first time I am doing something like this, so any assistance would be greatly appreciated.
Thanks.
I think what you're looking for is rails runner. I know in Rails 2.3.x you'd do
ruby script/runner <your file>
In Rails 3 it might be slightly different.
http://guides.rubyonrails.org/command_line.html#rails-runner
The primary difference between a runner and a rake task is : runner would boot rails while rake task doesn't (you can tell it to do so).
Since rake can do both (boot/no boot), there's no concept of runner in rails-3 anymore.
So, create a rake task: whatever_name.rake
Example:
desc "This task does awesome stuff"
task :do_awesome_stuff do
awesome_method
end
def awesome_method
#put your ruby code here
end
Now from your command prompt, type rake do_awesome_stuff to execute this rake task.
To make it boot Rails, change task definition to this:
task :do_awesome_stuff => :environment do