【问题标题】:How do I run Ruby tasks that use my Rails models?如何运行使用我的 Rails 模型的 Ruby 任务?
【发布时间】: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 正在幕后做所有神奇的工作来设置所有这些东西。那么如何设置我的小脚本呢?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案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】:
        【解决方案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 任务! :)

              这是一个例子

              1. 运行rails g task my_namespace my_task

              2. 这将生成一个名为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. 使用rake my_namespace:my_task 运行此任务

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-03-12
                • 2011-08-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-07-15
                相关资源
                最近更新 更多