如何运行使用Rails模型的Ruby任务?

时间:2022-06-26 07:21:56

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.

我有一个有一些基本模型的Rails应用。该网站显示从其他来源检索的数据。因此,我需要编写一个Ruby脚本,在数据库中创建新的实例。我知道我可以用测试钩子做这个,但我不确定这是否有意义。

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?).

我不确定这个任务应该是什么样子的,我如何调用它,或者它应该放在我的源树中的什么位置(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?

这之所以失败,是因为它无法获得到数据库的连接。这对我的新手来说是有意义的,因为Rails可能会在幕后完成所有神奇的工作来设置所有的东西。那么我该如何设置我的小脚本呢?

9 个解决方案

#1


7  

I agree with the answer above but you have to include => :environment in your task or it will not load the Rails environment.

我同意上面的答案,但是您必须在任务中包含=>:environment,否则它不会加载Rails环境。

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

#2


18  

You can load the entire rails environment in any ruby script by simply requiring environment.rb:

您可以通过简单地要求环境来加载任何ruby脚本中的整个rails环境。

require "#{ENV['RAILS_ROOT']}/config/environment" 

This assumes the RAILS_ROOT environment variable is set, see my comment for other ways of doing this.

这假设设置了RAILS_ROOT环境变量,请参阅我的注释以了解其他实现此功能的方法。

This has the added bonus of giving you all the nice classes and objects that you have in the rest of your rails code.

这有一个额外的好处,就是可以在rails代码的其余部分中提供所有优秀的类和对象。

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.

为了开始您的进程,cron似乎会做您想做的事情,我还将向您的capistrano菜谱添加一个任务,将您的脚本添加到crontab,以便定期从外部源获取数据并更新您的DB。这很容易用cronedit gem完成。

The cron approach does have some drawbacks, mostly overhead and control, for other more sophisticated options see HowToRunBackgroundJobsInRails from the rails wiki.

cron方法确实有一些缺点,主要是开销和控制,对于其他更复杂的选项,请参见来自rails wiki的HowToRunBackgroundJobsInRails。

#3


3  

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.

我建议创建自定义rake任务(lib/task/foo.rake)。这使您可以轻松访问rails应用程序的大部分功能。

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.

您甚至可以通过cronjob运行这些任务。

#4


2  

I wrote up a post about this a while back.

我以前写过一篇关于这个的文章。

http://www.rawblock.com/2007/06/14/ruby-oracle-mac-os-x-pain-jruby-and-activerecord-jdbc-to-the-rescue/

http://www.rawblock.com/2007/06/14/ruby-oracle-mac-os-x-pain-jruby-and-activerecord-jdbc-to-the-rescue/

#5


1  

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.

我相信有一种更优雅的方式可以做到这一点,这样它就可以从你的数据库中获取信息。

#6


1  

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.

你说你的网站从其他来源获取数据?多长时间?如果是半经常性的,你肯定想要了解后台处理/消息传递。如果经常需要避免在每次运行脚本时加载rails环境,因为每次都要支付过高的启动税。

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

脚本/Runner & Cron后台/RB Starling工作MemcacheQ Beanstalk后台作业(Bj) delayed_job (Dj)守护进程生成器

#7


1  

Check out my answer in "A cron job for rails: best practices?".

在“rails的cron工作:最佳实践?”

It contains two 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.

它包含两个示例,用于使用cron运行Rake任务和类方法(通过脚本/runner)。在这两种情况下,都加载了Rails,您可以使用您的模型。

#8


0  

Nice Joyent write up of using rake to run rails tasks from a cron job - http://wiki.joyent.com/accelerators:kb:rails:cron

漂亮的Joyent写的使用rake从cron任务运行rails任务- http://wiki.joyent.com/accelerators:kb:rails:cron

#9


0  

Easiest way to run ruby tasks that interact with rails app/models is to make Rails generate Rake tasks for you!! :)

运行与rails应用程序/模型交互的ruby任务的最简单方法是让rails为您生成Rake任务!:)

Here's an example

这里有一个例子

  1. run rails g task my_namespace my_task

    运行rails g任务my_namespace my_task

  2. This will generate a file called lib/tasks/my_namespace.rake which looks like:

    这将生成一个名为lib/tasks/my_namespace的文件。rake看起来像:

namespace :my_namespace do
desc "TODO: Describe your task here"
  task :my_task1 => :environment do
    #write any ruby code here and also work with your models
    puts User.find(1).name
  end
end
  1. Run this task with rake my_namespace:my_task

    使用rake my_namespace:my_task运行此任务

  2. Watch your ruby code task that interacts with rails modal run!

    观察与rails模式运行交互的ruby代码任务!

#1


7  

I agree with the answer above but you have to include => :environment in your task or it will not load the Rails environment.

我同意上面的答案,但是您必须在任务中包含=>:environment,否则它不会加载Rails环境。

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

#2


18  

You can load the entire rails environment in any ruby script by simply requiring environment.rb:

您可以通过简单地要求环境来加载任何ruby脚本中的整个rails环境。

require "#{ENV['RAILS_ROOT']}/config/environment" 

This assumes the RAILS_ROOT environment variable is set, see my comment for other ways of doing this.

这假设设置了RAILS_ROOT环境变量,请参阅我的注释以了解其他实现此功能的方法。

This has the added bonus of giving you all the nice classes and objects that you have in the rest of your rails code.

这有一个额外的好处,就是可以在rails代码的其余部分中提供所有优秀的类和对象。

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.

为了开始您的进程,cron似乎会做您想做的事情,我还将向您的capistrano菜谱添加一个任务,将您的脚本添加到crontab,以便定期从外部源获取数据并更新您的DB。这很容易用cronedit gem完成。

The cron approach does have some drawbacks, mostly overhead and control, for other more sophisticated options see HowToRunBackgroundJobsInRails from the rails wiki.

cron方法确实有一些缺点,主要是开销和控制,对于其他更复杂的选项,请参见来自rails wiki的HowToRunBackgroundJobsInRails。

#3


3  

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.

我建议创建自定义rake任务(lib/task/foo.rake)。这使您可以轻松访问rails应用程序的大部分功能。

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.

您甚至可以通过cronjob运行这些任务。

#4


2  

I wrote up a post about this a while back.

我以前写过一篇关于这个的文章。

http://www.rawblock.com/2007/06/14/ruby-oracle-mac-os-x-pain-jruby-and-activerecord-jdbc-to-the-rescue/

http://www.rawblock.com/2007/06/14/ruby-oracle-mac-os-x-pain-jruby-and-activerecord-jdbc-to-the-rescue/

#5


1  

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.

我相信有一种更优雅的方式可以做到这一点,这样它就可以从你的数据库中获取信息。

#6


1  

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.

你说你的网站从其他来源获取数据?多长时间?如果是半经常性的,你肯定想要了解后台处理/消息传递。如果经常需要避免在每次运行脚本时加载rails环境,因为每次都要支付过高的启动税。

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

脚本/Runner & Cron后台/RB Starling工作MemcacheQ Beanstalk后台作业(Bj) delayed_job (Dj)守护进程生成器

#7


1  

Check out my answer in "A cron job for rails: best practices?".

在“rails的cron工作:最佳实践?”

It contains two 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.

它包含两个示例,用于使用cron运行Rake任务和类方法(通过脚本/runner)。在这两种情况下,都加载了Rails,您可以使用您的模型。

#8


0  

Nice Joyent write up of using rake to run rails tasks from a cron job - http://wiki.joyent.com/accelerators:kb:rails:cron

漂亮的Joyent写的使用rake从cron任务运行rails任务- http://wiki.joyent.com/accelerators:kb:rails:cron

#9


0  

Easiest way to run ruby tasks that interact with rails app/models is to make Rails generate Rake tasks for you!! :)

运行与rails应用程序/模型交互的ruby任务的最简单方法是让rails为您生成Rake任务!:)

Here's an example

这里有一个例子

  1. run rails g task my_namespace my_task

    运行rails g任务my_namespace my_task

  2. This will generate a file called lib/tasks/my_namespace.rake which looks like:

    这将生成一个名为lib/tasks/my_namespace的文件。rake看起来像:

namespace :my_namespace do
desc "TODO: Describe your task here"
  task :my_task1 => :environment do
    #write any ruby code here and also work with your models
    puts User.find(1).name
  end
end
  1. Run this task with rake my_namespace:my_task

    使用rake my_namespace:my_task运行此任务

  2. Watch your ruby code task that interacts with rails modal run!

    观察与rails模式运行交互的ruby代码任务!