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

Posted

技术标签:

【中文标题】如何运行使用我的 Rails 模型的 Ruby 任务?【英文标题】:How do I run Ruby tasks that use my Rails models? 【发布时间】:2010-09-22 12:57:28 【问题描述】:

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

我不确定这个任务应该是什么样子,我如何调用它,或者它应该在我的源代码树中的什么位置(lib\tasks?)。

例如,这是我的第一次尝试:

require 'active_record'
require '../app/models/mymodel.rb'

test = MyModel.new
test.name = 'test'
test.save

这会失败,因为它无法连接到数据库。这对我的新手大脑来说是一种模糊的方式,因为大概 Rails 正在幕后做所有神奇的工作来设置所有这些东西。那么如何设置我的小脚本呢?

【问题讨论】:

【参考方案1】:

您可以在任何 ruby​​ 脚本中加载整个 rails 环境,只需要求 environment.rb:

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

这假设设置了 RAILS_ROOT 环境变量,请参阅我的评论了解其他方法。

这还有一个额外的好处,就是为您提供了您在 Rails 代码的其余部分中拥有的所有不错的类和对象。

要启动您的流程,听起来 cron 会执行您想要的操作,我还会在您的 capistrano 配方中添加一个任务,该任务会将您的脚本添加到 crontab 以定期从外部源获取数据并更新您的数据库.这可以通过cronedit gem 轻松完成。

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

【讨论】:

你知道 RAILS_ROOT 直到 environment.rb 已经被加载后才被定义? :-) Orion 非常正确。所以我编辑了上面的内容来寻找环境变量。您还可以提供完整路径或使用相对于您的脚本的路径 "#File.dirname(FILE)/path/to/env"【参考方案2】:

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

例如,

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

【讨论】:

【参考方案3】:

我建议创建自定义 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

然后:

$ rake -T foo
rake foo:something_cool       # do something cool

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

【讨论】:

【参考方案4】:

不久前我写了一篇关于这个的帖子。

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

【讨论】:

【参考方案5】:

您可以像这样在脚本中打开连接:

ActiveRecord::Base.establish_connection(
    :adapter  => "mysql",
    :username => "root",
    :host     => "localhost",
    :password => "******",
    :database => "******" 
)

我确信有一种更优雅的方法可以做到这一点,以便它从您的 database.yml 中获取信息。

【讨论】:

【参考方案6】:

这需要几个步骤,并且需要更多细节才能真正回答好。

您说您的网站从其他来源检索数据?多常?如果它是半定期的,您肯定想查看后台处理/消息传递。如果你真的很想避免每次脚本运行时都加载你的 rails 环境,因为你每次都会支付太高的启动税。

您需要研究多种选择。阅读他们中的每一个,特别是那些发布他们为什么做出选择的人的评论,会让你很好地了解在做出选择之前你需要问自己哪些问题。加载数据的工作量有多大?等等……

在我的脑海中,这些是您可能想要研究的一些事情

脚本/Runner & Cron 背景/RB 八哥 工作 内存缓存Q 豆茎 后台作业 (Bj) 延迟作业(DJ) 守护进程生成器

【讨论】:

【参考方案7】:

在“A cron job for rails: best practices?”中查看我的答案。

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

【讨论】:

谢谢....这不是我要找的帖子,但您的解决方案为我开辟了新的可能性...:D【参考方案8】:

关于使用 rake 从 cron 作业运行 rails 任务的精彩 Joyent 文章 - http://wiki.joyent.com/accelerators:kb:rails:cron

【讨论】:

【参考方案9】:

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

这是一个例子

    运行rails g task my_namespace my_task

    这将生成一个名为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

    使用rake my_namespace:my_task 运行此任务

    观看与 rails modal 交互的 ruby​​ 代码任务!

【讨论】:

以上是关于如何运行使用我的 Rails 模型的 Ruby 任务?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 生成模型

如何检查特定属性是不是是有效的 ruby​​ on rails

Ruby/Rails:您如何自定义 Devise 的邮件模板?

Ruby/Rails:您如何自定义 Devise 的邮件模板?

如何在我的 Ruby on Rails 应用程序上使用 ruby​​ 2.7

Ruby on Rails:获取模型中的下一项