diff --git a/lib/whenever.rb b/lib/whenever.rb index 4801211..8fbd12c 100644 --- a/lib/whenever.rb +++ b/lib/whenever.rb @@ -13,10 +13,7 @@ end # Whenever files require 'whenever/base' require 'whenever/job_list' -require 'whenever/job_types/default' -require 'whenever/job_types/user_defined' -require 'whenever/job_types/rake_task' -require 'whenever/job_types/runner' +require 'whenever/job' require 'whenever/outputs/cron' require 'whenever/outputs/cron/output_redirection' require 'whenever/command_line' diff --git a/lib/whenever/job.rb b/lib/whenever/job.rb new file mode 100644 index 0000000..636bc49 --- /dev/null +++ b/lib/whenever/job.rb @@ -0,0 +1,22 @@ +module Whenever + class Job + + attr_accessor :at, :output_redirection + + def initialize(options = {}) + @options = options + + @at = options[:at] + @output_redirection = options.has_key?(:output) ? options[:output] : :not_set + @options[:environment] ||= :production + @options[:path] ||= Whenever.path + end + + def output + @options[:template].gsub(/:\w+/) do |key| + @options[key.sub(':', '').to_sym] + end + end + + end +end \ No newline at end of file diff --git a/lib/whenever/job_list.rb b/lib/whenever/job_list.rb index d9c2f3b..7615b29 100644 --- a/lib/whenever/job_list.rb +++ b/lib/whenever/job_list.rb @@ -2,8 +2,7 @@ module Whenever class JobList def initialize(options) - @jobs = Hash.new - @env = Hash.new + @jobs, @env, @set_variables = {}, {}, {} case options when String @@ -16,7 +15,12 @@ module Whenever end pre_set(options[:set]) end - + + # Load all job type files. + Dir["#{File.expand_path(File.dirname(__FILE__))}/job_types/*.rb"].each do |file| + eval(File.read(file)) + end + eval(config) end @@ -25,6 +29,7 @@ module Whenever instance_variable_set("@#{variable}".to_sym, value) self.class.send(:attr_reader, variable.to_sym) + @set_variables[variable] = value end def env(variable, value) @@ -37,41 +42,22 @@ module Whenever yield end - def command(task, options = {}) - # :cron_log was an old option for output redirection, it remains for backwards compatibility - options[:output] = (options[:cron_log] || @cron_log) if defined?(@cron_log) || options.has_key?(:cron_log) - # :output is the newer, more flexible option. - options[:output] = @output if defined?(@output) && !options.has_key?(:output) - options[:class] ||= Whenever::Job::Default - @jobs[@current_time_scope] ||= [] - @jobs[@current_time_scope] << options[:class].new(@options.merge(:task => task).merge(options)) - end - - def job_type(name, options = {}, &block) - (class << self; self; end).class_eval do - define_method(name) do |task,*args| - new_job = Whenever::Job::UserDefined.new - block.call(new_job) - options = new_job.to_options - options.merge!(args[0]) if args[0].is_a?(Hash) - options.reverse_merge!(:environment => @environment, :path => @path) - options[:class] = Whenever::Job::UserDefined - command(task, options) + def job_type(name, template) + class_eval do + define_method(name) do |task, *args| + options = { :task => task, :template => template } + options.merge!(args[0]) if args[0].is_a? Hash + + # :cron_log was an old option for output redirection, it remains for backwards compatibility + options[:output] = (options[:cron_log] || @cron_log) if defined?(@cron_log) || options.has_key?(:cron_log) + # :output is the newer, more flexible option. + options[:output] = @output if defined?(@output) && !options.has_key?(:output) + + @jobs[@current_time_scope] ||= [] + @jobs[@current_time_scope] << Whenever::Job.new(@options.merge(@set_variables).merge(options)) end end end - - def runner(task, options = {}) - options.reverse_merge!(:environment => @environment, :path => @path) - options[:class] = Whenever::Job::Runner - command(task, options) - end - - def rake(task, options = {}) - options.reverse_merge!(:environment => @environment, :path => @path) - options[:class] = Whenever::Job::RakeTask - command(task, options) - end def generate_cron_output set_path_environment_variable @@ -93,7 +79,7 @@ module Whenever pairs.each do |pair| next unless pair.index('=') variable, value = *pair.split('=') - set(variable.strip, value.strip) unless variable.blank? || value.blank? + set(variable.strip.to_sym, value.strip) unless variable.blank? || value.blank? end end diff --git a/lib/whenever/job_types/default.rb b/lib/whenever/job_types/default.rb index 7b7af8f..2eaf56e 100644 --- a/lib/whenever/job_types/default.rb +++ b/lib/whenever/job_types/default.rb @@ -1,27 +1,3 @@ -module Whenever - module Job - class Default - - attr_accessor :task, :at, :output, :output_redirection - - def initialize(options = {}) - @task = options[:task] - @at = options[:at] - @output_redirection = options.has_key?(:output) ? options[:output] : :not_set - @environment = options[:environment] || :production - @path = options[:path] || Whenever.path - end - - def output - task - end - - protected - - def path_required - raise ArgumentError, "No path available; set :path, '/your/path' in your schedule file" if @path.blank? - end - - end - end -end \ No newline at end of file +job_type :command, ':task' +job_type :runner, 'cd :path && script/runner -e :environment ":task"' +job_type :rake, 'cd :path && RAILS_ENV=:environment /usr/bin/env rake :task' \ No newline at end of file diff --git a/lib/whenever/job_types/rake_task.rb b/lib/whenever/job_types/rake_task.rb deleted file mode 100644 index 360e173..0000000 --- a/lib/whenever/job_types/rake_task.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Whenever - module Job - class RakeTask < Whenever::Job::Default - - def output - path_required - "cd #{@path} && RAILS_ENV=#{@environment} /usr/bin/env rake #{task}" - end - - end - end -end diff --git a/lib/whenever/job_types/runner.rb b/lib/whenever/job_types/runner.rb deleted file mode 100644 index edbb4f0..0000000 --- a/lib/whenever/job_types/runner.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Whenever - module Job - class Runner < Whenever::Job::Default - - def output - path_required - %Q(cd #{File.join(@path)} && script/runner -e #{@environment} #{task.inspect}) - end - - end - end -end diff --git a/lib/whenever/job_types/user_defined.rb b/lib/whenever/job_types/user_defined.rb deleted file mode 100644 index 1cd5df3..0000000 --- a/lib/whenever/job_types/user_defined.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Whenever - module Job - class UserDefined < Whenever::Job::Default - attr_accessor :command, :settings - - def initialize(opts={}) - super - @command = opts[:command] - @settings = opts[:settings] ||= {} - end - - def to_options - { :command => command, :settings => settings } - end - - def output - [ cd_path, bundler, command, app_environment, quoted_task ].compact.join(" ") - end - - private - - def cd_path - parse_setting :path, "cd #{settings[:path]} &&", "cd #{File.join(@path)} &&" - end - - def app_environment - parse_setting :environment, "-e #{settings[:environment]}", "-e #{@environment}" - end - - def bundler - "bundle exec" if settings[:use_bundler] - end - - def parse_setting(name, with_option, without_option) - if settings.has_key? name - with_option if settings[name] - else - without_option - end - end - - def quoted_task - settings[:quote_task] == false ? task : task.inspect - end - - end - end -end \ No newline at end of file diff --git a/test/output_defined_job_test.rb b/test/output_defined_job_test.rb new file mode 100644 index 0000000..308e0aa --- /dev/null +++ b/test/output_defined_job_test.rb @@ -0,0 +1,87 @@ +require File.expand_path(File.dirname(__FILE__) + "/test_helper") + +class OutputDefinedJobTest < Test::Unit::TestCase + + context "A defined job with a :task" do + setup do + @output = Whenever.cron \ + <<-file + job_type :some_job, "before :task after" + every 2.hours do + some_job "during" + end + file + end + + should "output the defined job with the task" do + assert_match /^.+ .+ .+ .+ before during after$/, @output + end + end + + context "A defined job with a :task and some options" do + setup do + @output = Whenever.cron \ + <<-file + job_type :some_job, "before :task after :option1 :option2" + every 2.hours do + some_job "during", :option1 => 'happy', :option2 => 'birthday' + end + file + end + + should "output the defined job with the task and options" do + assert_match /^.+ .+ .+ .+ before during after happy birthday$/, @output + end + end + + context "A defined job with a :task and an option where the option is set globally" do + setup do + @output = Whenever.cron \ + <<-file + job_type :some_job, "before :task after :option1" + set :option1, 'happy' + every 2.hours do + some_job "during" + end + file + end + + should "output the defined job with the task and options" do + assert_match /^.+ .+ .+ .+ before during after happy$/, @output + end + end + + context "A defined job with a :task and an option where the option is set globally and locally" do + setup do + @output = Whenever.cron \ + <<-file + job_type :some_job, "before :task after :option1" + set :option1, 'global' + every 2.hours do + some_job "during", :option1 => 'local' + end + file + end + + should "output the defined job using the local option" do + assert_match /^.+ .+ .+ .+ before during after local$/, @output + end + end + + context "A defined job with a :task and an option that is not set" do + setup do + @output = Whenever.cron \ + <<-file + job_type :some_job, "before :task after :option1" + every 2.hours do + some_job "during", :option2 => 'happy' + end + file + end + + should "output the defined job with that option removed" do + assert_match /^.+ .+ .+ .+ before during after$/, @output + end + end + +end \ No newline at end of file diff --git a/test/output_runner_test.rb b/test/output_runner_test.rb index ee02168..9bb1411 100644 --- a/test/output_runner_test.rb +++ b/test/output_runner_test.rb @@ -70,24 +70,6 @@ class OutputRunnerTest < Test::Unit::TestCase end end - context "A runner with no path set and no RAILS_ROOT defined" do - setup do - Whenever.stubs(:path).returns(nil) - - @input = <<-file - every 2.hours do - runner "blahblah" - end - file - end - - should "raise an exception" do - assert_raises ArgumentError do - Whenever.cron(@input) - end - end - end - context "A runner with an environment set" do setup do @output = Whenever.cron \ @@ -190,20 +172,4 @@ class OutputRunnerTest < Test::Unit::TestCase end end - context "A runner which makes use of double quotes" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - every 2.hours do - runner 'Product.import("http://example.com/product.xml")' - end - file - end - - should "output the runner using the original environmnet" do - assert_match two_hours + ' cd /my/path && script/runner -e production "Product.import(\"http://example.com/product.xml\")"', @output - end - end - end diff --git a/test/output_user_defined_test.rb b/test/output_user_defined_test.rb deleted file mode 100644 index 571b990..0000000 --- a/test/output_user_defined_test.rb +++ /dev/null @@ -1,307 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + "/test_helper") - -class OutputUserDefinedTest < Test::Unit::TestCase - - context "A custom job type" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job" do - assert_match two_hours + ' cd /my/path && hello -e production "blahblah"', @output - end - end - - context "A custom job type which does not quote the task" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :quote_task => false } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job and not quote the task" do - assert_match two_hours + ' cd /my/path && hello -e production blahblah', @output - end - end - - context "A custom job type with no path" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :path => false } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job without changing directory first" do - assert_match two_hours + ' hello -e production "blahblah"', @output - end - end - - context "A custom job type with path" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :path => "/path/to/app" } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job and a custom path" do - assert_match two_hours + ' cd /path/to/app && hello -e production "blahblah"', @output - end - end - - context "A custom job which uses bunder" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :use_bundler => true } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job with bundler" do - assert_match two_hours + ' cd /my/path && bundle exec hello -e production "blahblah"', @output - end - end - - context "A custom job which uses bunder and a custom path" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :use_bundler => true, :path => "/path/to/app" } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job with bundler and a custom path" do - assert_match two_hours + ' cd /path/to/app && bundle exec hello -e production "blahblah"', @output - end - end - - context "A custom job with settings set individually" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings[:use_bundler] = true - job.settings[:path] = "/path/to/app" - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command with all the settings as expected" do - assert_match two_hours + ' cd /path/to/app && bundle exec hello -e production "blahblah"', @output - end - end - - context "A custom job which doesn't use an environment" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :environment => false } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the command using simple_job without environment" do - assert_match two_hours + ' cd /my/path && hello "blahblah"', @output - end - end - - context "A custom job that overrides the path set" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah", :path => '/some/other/path' - end - file - end - - should "output the runner using that path" do - assert_match two_hours + ' cd /some/other/path && hello -e production "blahblah"', @output - end - end - - context "A custom job that overrides the path set from the job_type definition" do - setup do - @output = Whenever.cron \ - <<-file - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :path => "/some/other/path" } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the runner using that path" do - assert_match two_hours + ' cd /some/other/path && hello -e production "blahblah"', @output - end - end - - context "A custom job with an environment set" do - setup do - @output = Whenever.cron \ - <<-file - set :environment, :silly - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the runner using that environment" do - assert_match two_hours + ' cd /my/path && hello -e silly "blahblah"', @output - end - end - - context "A custom job that overrides the environment set" do - setup do - @output = Whenever.cron \ - <<-file - set :environment, :silly - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah", :environment => :serious - end - file - end - - should "output the runner using that environment" do - assert_match two_hours + ' cd /my/path && hello -e serious "blahblah"', @output - end - end - - context "A custom job that overrides the environment set in the job_type definition" do - setup do - @output = Whenever.cron \ - <<-file - set :environment, :silly - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - job.settings = { :environment => :serious } - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the runner using that environment" do - assert_match two_hours + ' cd /my/path && hello -e serious "blahblah"', @output - end - end - - context "A custom job where the environment is overridden using the :set option" do - setup do - @output = Whenever.cron :set => 'environment=serious', :string => \ - <<-file - set :environment, :silly - set :path, '/my/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the runner using the override environment" do - assert_match two_hours + ' cd /my/path && hello -e serious "blahblah"', @output - end - end - - context "A custom job where the environment and path are overridden using the :set option" do - setup do - @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \ - <<-file - set :environment, :silly - set :path, '/silly/path' - job_type :simple_job do |job| - job.command = "hello" - end - every 2.hours do - simple_job "blahblah" - end - file - end - - should "output the runner using the overridden path and environment" do - assert_match two_hours + ' cd /serious/path && hello -e serious "blahblah"', @output - end - end - - - -end