I have a Rails app with some basic models. The website displays data retrieved from other sources. So I need to write a Ruby script that creates new instances in my database. I know I can do that with the test hooks, but I'm not sure that makes sense here.
I'm not sure what this task should look like, how I can invoke it, or where it should go in my source tree (lib\tasks?).
For example, here's my first try:
require 'active_record'
require '../app/models/mymodel.rb'
test = MyModel.new
test.name = 'test'
test.save
This fails because it can't get a connection to the database. This makes sense in a vague way to my newbie brain, since presumably Rails is doing all the magic work behind the scenes to set all that stuff up. So how do I set up my little script?
-
You can open a connection in your scripts as such:
ActiveRecord::Base.establish_connection( :adapter => "mysql", :username => "root", :host => "localhost", :password => "******", :database => "******" )
I'm sure there is a more elegant way to do it, so that it grabs the info from your database.yml.
-
I'd suggest creating custom rake tasks (lib/task/foo.rake). This give you easy access to most of the functionality of your rails app.
namespace :foo do desc 'do something cool' def something_cool test = MyModel.new test.name = 'test' test.save end end
Then:
$ rake -T foo rake foo:something_cool # do something cool
You can even run the tasks via a cronjob.
-
You can load the entire rails environment in any ruby script by simply requiring environment.rb:
require "#{ENV['RAILS_ROOT']}/config/environment"
This assumes the RAILS_ROOT environment variable is set, see my comment for other ways of doing this.
This has the added bonus of giving you all the nice classes and objects that you have in the rest of your rails code.
To kick off your processes it sounds like cron will do what you want, and I would also add a task to your capistrano recipe that would add your script to the crontab to periodically get the data from the external source and update your DB. This can easily be done with the cronedit gem.
The cron approach does have some drawbacks, mostly overhead and control, for other more sophisticated options see HowToRunBackgroundJobsInRails from the rails wiki.
Orion Edwards : You do realise that RAILS_ROOT isn't defined until environment.rb has already been loaded? :-)csexton : Orion is very much correct. So I edited the above to look for the environment variable. You could also provide a full path or use one relative to your script with "#{File.dirname(__FILE__)}/path/to/env" -
I agree with the answer above but you have to include => :environment in your task or it will not load the Rails environment.
e.g.,
namespace :send do namespace :trial do namespace :expiry do desc "Sends out emails to people who's accounts are about to expire" task :warnings => :environment do User.trial_about_to_expire.has_not_been_notified_of_trial_expiry.each do |user| UserMailer.deliver_trial_expiring_warning(user) user.notified_of_trial_expiry = true user.save end end end end end
-
There are few steps to this and more details needed to really answer well.
You say your site retrieves data from other sources? How often? If it is semi-regularly you definitely want to look into background processing/messaging. If it is frequently you really want to avoid loading your rails environment every time your script runs since you will be paying too high a startup tax each time.
There are a multitude of options out there you will want to research. Reading about each of them, particularly reviews from people who post about why they made the choice they did, will give you a good feel for what questions you need to ask yourself before you make your choice. How big a job is loading the data? etc...
Off the top of my head these are some of the things you may want to look into
Script/Runner & Cron Background/RB Starling Workling MemcacheQ Beanstalk Background Job (Bj) delayed_job (Dj) Daemon Generator
-
I wrote up a post about this a while back.
-
Nice Joyent write up of using rake to run rails tasks from a cron job - http://wiki.joyent.com/accelerators:kb:rails:cron
-
Check out a relatively short answer I gave on another question.
It contains 2 examples for using cron to run rake tasks and class methods (via script/runner). In both cases, Rails is loaded and you can use your models.
0 comments:
Post a Comment