如何运行使用我的 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/Rails:您如何自定义 Devise 的邮件模板?
Ruby/Rails:您如何自定义 Devise 的邮件模板?