Running Rake Without Shell Access? - ruby-on-rails

For a RoR installation, is there any way to run rake commands without root access?
To put it another way, is there any way to get db:create and db:migrate to be run without root access (perhaps automatically or something)? Or can I run rake commands from a RoR controller?

Take a look at rails-2.X.X/lib/tasks/databases.rake and you can see the code called to create, drop, and migrate your database.
Once a rails environment is initialized, you can use the code inside the rake task file to create, drop, and migrate.
I do not know if you can do this at the controller level before it errors, but you can always try. You could also do it after rails has finished initializing in the environment file.
config/environment.rb
...
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate(File.join(Rails.root, 'db', 'migrate'))

Well, it is a bit of a chicken-egg problem, you may be able to start your RoR instance without the database created but I doubt it. If your hosting provider is able to host RoR apps, there must be a way for them to run rake for you or to let you run it somehow.

Since it sounds like you are running into troubles with creating the database, is there a way to do it from the hosting control panel? Still, how are you going to migrate your database? Sounds like you might need to look at a new host. I use Slicehost and think they are great :)

Give this code a try:
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'tasks/rails'
Rake::Task["db:version"].invoke
I just tried it in ./script/console and that worked. It wouldn't work without the require lines.
I use it to call other rake tasks from a rake task (when it's not a pre-req but something that has to happen in the middle).
Note, that won't get you any of the output from the command. If you want that you could just go with good old backticks and run the command like this:
output = `rake db:version`
That'll launch another process, but I don't think there's a problem with that.

Just to be clear, you do not need root access, you need just shell (ssh) access to that machine.
How are you deploying it without access ? If you're using capistrano than you already have shell access and it can run those tasks for you.

Related

Rake task during application initialization rails

I want to execute a rake task when the server of my application starts.
In config/application.rb i put the following:
if !Rails.env.production?
Rake::Task[ "init:db_records" ].invoke
end
The rake task is well defined, and runs without a problem if i invode it from terminal
rake init:db_records
But when placed in config/application.rb (or even in any initializers/*) i got the following error.
Don't know how to build task 'init:db_records'
What is the way to execute a rake task when the server starts ?
Thanks!
Rails already has a mechanism for setting up a development database -- rake db:seed. It does not run automatically when you start the app, but it does run as part of rake db:setup.
Unless you have a good reason, it's usually best to stick the conventions that Rails provides.
For those who encounter the same problem in the future.
I achieved this by creating a new file in the initializers directory, where i put the code of the rake task.
The advantage of this at this point, is that the application is already loaded, so you have access to ActiveRecord functions...
Putting the code directly in config/application.rb didn't work, since my models were not loaded yet.
Hope it will help!
Your Rake tasks are (likely) defined in a Rakefile. The initializer has no idea that file even exists, so it doesn't know about the tasks within.
The easiest way to circumvent this is by doing something like this:
Dir.chdir(Rails.root) do
`rake init:db_records`
end
That is, change the working directory to the root rails directory, then running the command.

Rails 4: stop `rake` from running all rake tasks

A developer had authority to drop a DB but not re-create it. While working on a rake tasks, he accidentally ran the entire rake suite, which included destroying the development DB but without the proper authority to re-create and populate it.
How can I ensure this doesn't happen again? Is there someway in the Rails app to override running rake so that it does NOT execute a bunch of unspecified tasks?
The developer was looking for a list of tasks and figured that running rake would provide that listing, similarly to how running rails by itself puts out instructions.
I know there's a binstub for rake, but I really do not know what happens if I mess with things in there.
Are there any good solutions to a situation like this?
Set the default task? IIRC, outside of a namespace block:
task :default => "something_that_doesnt_destroy_the_world"
Taking a note from Dave's answer and another SO question (couldn't find link again), here is how you can override the default rake tasks in Rails 4.
# lib/tasks/default.rake (name is not important)
namespace :override do
task :default do
puts "This is now the default rake task executed via 'rake'"
end
end
# Remove default task and switch to above (still in same file)
task(:default).clear.enhance ["override:default"]
At the terminal:
$ rake
/lib/tasks/default.rake: this is now the default 'rake' task
If there is a "cleaner" or more "conventional" Rails way, anyone's welcome to shout it out. This is the "cleanest" solution I could find.

Rails can't execute rake task

Rails won't fire off a rake command from my controller because it can't find rake. I know this because I experienced this in my dev environment and fixed it by giving it the absolute path to rake. However this solution isn't working my production environment.
Things I know:
I can run the rake task rom cli
I can run it through irb with a: system "rake ..."
I can't find any errors!
Rakes:
/usr/lib/ruby/1.9.1/rake
/usr/lib/ruby/gems/1.9.1/bin/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.9.2/lib/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.9.2/bin/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/bin/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.8.7/lib/rake
/usr/lib/ruby/gems/1.9.1/gems/rake-0.8.7/bin/rake
/usr/bin/rake
/var/lib/gems/1.8/bin/rake
/var/lib/gems/1.8/doc/rake-0.9.2.2/rdoc/lib/rake
/var/lib/gems/1.8/gems/rake-0.9.2.2/lib/rake
/var/lib/gems/1.8/gems/rake-0.9.2.2/bin/rake
/var/lib/gems/1.8/gems/rake-0.8.7/lib/rake
/var/lib/gems/1.8/gems/rake-0.8.7/bin/rake
/var/lib/gems/1.8/gems/sprockets-2.3.1/lib/rake
How in the heck do I go about troubleshooting this???
The rake task I was calling in production was failing because of my attempt to dump it's contents into a log with logger disabled.
system "rake invite INVITE_ID=5 RAILS_ENV=production >> /root/log/rake.log &"
Thanks for all your help...sorry for being so vague. I was just looking for quick responses hoping I was doing something stupid. Which I was. I SWEAR I tried it without the log entry...probably moving too fast like I always do.
Also, just to answer a couple questions. The rake task I'm using is an internal tool I use myself for some maintenance and want to simply offload that task to my coworker who uses an app I've built. There's no need to industrialize it with a scheduler, etc...

How to tell when Rails app is activated by migration?

I'm trying to create a migration for my app, and in this app I'm using a gem that tries to startup a different service upon app startup. Apparently, creating a migration...
rails generate migration AddSomeStuffToTable stuff:string
...activates the app, and this gem which tries to connect to startup the service. It appears that starting up the app via generating a migration makes the service startup unable to connect, so it just keeps sleeping and trying again, never actually running the migration.
In this gem, I've already dealt with this for rake, so this is what I've got so far:
MyService.start unless defined? Rake or defined? IRB
This handles the rake problem (like rake db:migrate, rake db:populate), but how can I handle the creation of migration, which (as far as I know) is not a Rake task?
You could try using environment variables for disabling the service:
MyService.start unless ENV['NO_SERVICE']
And run your command like this:
NO_SERVICE=1 rails generate migration AddSomeStuffToTable stuff:string
However, I doubt this scales well, especially if multiple developers are in the app. A better approach might be to do the reverse of this, to only start the service if a particular env variable is present. However, going this direction, you'd need to make sure your app servers set this variable, for example:
Apache: SetEnv START_SERVICE 1
nginx: env START_SERVICE=1
thin: START_SERVICE=1 thin start

Expose Rails App Environment to Ruby Script

Out of pure curiosity, I am wondering if it's possible (no doubt it is) to 'hook into' a Rails Application's environment. So for example, say I want to create a cron script (I don't) that operates some sort of maintenance on a Rails app, and I want to write it in Ruby and using all of the nice code that I already have, for example, User.find etc.
Is this possible, and if so, how?
I'm just curious, as I feel I would eventually want to do this for some reason or other.
I'm currently on Rails 3 with Ruby 1.9.1, in case it matters.
This is certainly possible. Here is a good writeup on how to do that: How to run a rake task from cron
Take a look at the Rails::Railtie class. If you need to run code code when you start up your app, this is a way to do it. Here's a very simple example.
From the beginning of Rails there is ./script/runner, designed exactly for such kind of problems.
In Rails 3 you call it as: ./script/rails runner "puts User.find(:all).map(&:inspect)"
Try ./script/runner --help or ./script/rails runner --help
As the argument to the runner you provide a filename or just a code.
It's often more useful than preparing a Rake task, because you can execute just one-time actions:
ssh prod#example.com "cd rails/app && ./script/runner -e production 'puts User.count'"
You could either use script/rails runner as suggested by Arsen7 or you could write your own script in which you load the app environment in the beginning:
require 'config/environment'
is actually everything you need.
To have your script working in a cron job, make sure that it is executable (chmod u+x) and that it starts with a correct shebang line (#!/usr/bin/env ruby or whatever is appropriate for your situation).
yeah just require these file at top of your script file
require 'config/boot.rb'
require 'config/application.rb'
Rails.application.require_environment!
Now you'll have access to your models

Resources