diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..31b73af00 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,92 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + ruby: ['2.7', '3.0', '3.1', '3.2', jruby-head, ruby-head] + rails_version: + - '6.0.0' + - '6.1.0' + - '7.0.0' + - 'edge' + include: + # Rails 5.2 + - ruby: 2.6 + rails_version: '5.2.0' + - ruby: 2.7 + rails_version: '5.2.0' + - ruby: jruby-9.2 + rails_version: '5.2.0' + + # Ruby 2.6 + - ruby: 2.6 + rails_version: '6.0.0' + - ruby: 2.6 + rails_version: '6.1.0' + + # jruby-9.2 + - ruby: jruby-9.2 + rails_version: '6.0.0' + - ruby: jruby-9.2 + rails_version: '6.1.0' + + # jruby-9.4 + - ruby: jruby-9.4 + rails_version: '7.0.0' + - ruby: jruby-9.4 + rails_version: 'edge' + + # + # The past + # + # EOL Active Record + - ruby: 2.2 + rails_version: '3.2.0' + - ruby: 2.1 + rails_version: '4.1.0' + - ruby: 2.4 + rails_version: '4.2.0' + - ruby: 2.4 + rails_version: '5.0.0' + - ruby: 2.5 + rails_version: '5.1.0' + + continue-on-error: ${{ matrix.rails_version == 'edge' || endsWith(matrix.ruby, 'head') }} + + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + env: + RAILS_VERSION: ${{ matrix.rails_version }} + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Run tests + env: + RAILS_VERSION: ${{ matrix.rails_version }} + run: bundle exec rspec + - name: Coveralls Parallel + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + flag-name: run-${{ matrix.ruby }}-${{ matrix.rails_version }} + parallel: true + + finish: + needs: test + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + parallel-finished: true diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml new file mode 100644 index 000000000..739473987 --- /dev/null +++ b/.github/workflows/rubocop.yml @@ -0,0 +1,30 @@ +name: RuboCop + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby 2.7 + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + - name: Generate lockfile for cache key + run: bundle lock + - name: Cache gems + uses: actions/cache@v1 + with: + path: vendor/bundle + key: ${{ runner.os }}-rubocop-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-rubocop- + - name: Install gems + run: | + bundle config path vendor/bundle + bundle config set without 'default test' + bundle install --jobs 4 --retry 3 + - name: Run RuboCop + run: bundle exec rubocop diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c0ddcc183..000000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: ruby -branches: - only: - - master -env: - global: - - JRUBY_OPTS="$JRUBY_OPTS --debug" - matrix: - - RAILS_VERSION="~> 4.2.0" - - RAILS_VERSION="~> 5.0.0" - - RAILS_VERSION="~> 5.1.0" - - RAILS_VERSION="edge" -rvm: - - 2.2.9 - - 2.3.6 - - 2.4.3 - - 2.5.0 - - jruby-9.1.15.0 - - jruby-head - - ruby-head -before_install: - - "gem install bundler" -jdk: oraclejdk8 -matrix: - allow_failures: - - rvm: jruby-head - - rvm: ruby-head - - env: RAILS_VERSION="edge" - - rvm: jruby-9.1.15.0 - env: RAILS_VERSION="~> 5.1.0" - fast_finish: true - # legacy testing - # things still run and we don't have a good reason to break it - # but we don't need to keep running the full matrix - include: - - rvm: 2.3.6 - env: RAILS_VERSION="~> 3.0.0" - - rvm: 2.3.6 - env: RAILS_VERSION="~> 3.1.0" - - rvm: 2.3.6 - env: RAILS_VERSION="~> 3.2.0" - - rvm: 2.3.6 - env: RAILS_VERSION="~> 4.0.0" - - rvm: 2.3.6 - env: RAILS_VERSION="~> 4.1.0" - - rvm: 2.1.10 - env: RAILS_VERSION="~> 4.2.0" - exclude: - - rvm: 2.2.9 - env: RAILS_VERSION="edge" -sudo: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 97614530f..86d801219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,42 @@ +4.1.11 - 2022-09-28 +=================== +* Fix missing require for Rails 7.0.3+ + +4.1.10 - 2022-01-17 +=================== +* Support for Rails 7.0. NOTE: If you are using Delayed Job independent of Rails, Active Support 7 has dropped classic dependency autoloading. You will need to add and setup zeitwerk for autoloading to continue working in ActiveSupport 7. + +4.1.9 - 2020-12-09 +================== +* Support for Rails 6.1 +* Add support for parameterized mailers via delay call (#1121) + +4.1.8 - 2019-08-16 +================== +* Support for Rails 6.0.0 + +4.1.7 - 2019-06-20 +================== +* Fix loading Delayed::PerformableMailer when ActionMailer isn't loaded yet + +4.1.6 - 2019-06-19 +================== +* Properly initialize ActionMailer outside railties (#1077) +* Fix Psych load_tags support (#1093) +* Replace REMOVED with FAILED in log message (#1048) +* Misc doc updates (#1052, #1074, #1064, #1063) + +4.1.5 - 2018-04-13 +================== +* Allow Rails 5.2 + 4.1.4 - 2017-12-29 -================= +================== * Use `yaml_tag` instead of deprecated `yaml_as` (#996) * Support ruby 2.5.0 4.1.3 - 2017-05-26 -================= +================== * Don't mutate the options hash (#877) * Log an error message when a deserialization error occurs (#894) * Adding the queue name to the log output (#917) diff --git a/Gemfile b/Gemfile index ab189562d..729110036 100644 --- a/Gemfile +++ b/Gemfile @@ -3,21 +3,40 @@ source 'https://rubygems.org' gem 'rake' platforms :ruby do - gem 'sqlite3' + # Rails 5.1 is the first to work with sqlite 1.4 + # Rails 6 now requires sqlite 1.4 + if ENV['RAILS_VERSION'] && ENV['RAILS_VERSION'] < '5.1' + gem 'sqlite3', '< 1.4' + else + gem 'sqlite3' + end end platforms :jruby do - if ENV['RAILS_VERSION'] == '~> 4.2.0' + if ENV['RAILS_VERSION'] == '4.2.0' gem 'activerecord-jdbcsqlite3-adapter', '< 50.0' + elsif ENV['RAILS_VERSION'] == '5.0.0' + gem 'activerecord-jdbcsqlite3-adapter', '~> 50.0' + elsif ENV['RAILS_VERSION'] == '5.1.0' + gem 'activerecord-jdbcsqlite3-adapter', '~> 51.0' + elsif ENV['RAILS_VERSION'] == '5.2.0' + gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0' + elsif ENV['RAILS_VERSION'] == '6.0.0' + gem 'activerecord-jdbcsqlite3-adapter', '~> 60.0' + elsif ENV['RAILS_VERSION'] == '6.1.0' + gem 'activerecord-jdbcsqlite3-adapter', '~> 61.0' else gem 'activerecord-jdbcsqlite3-adapter' end gem 'jruby-openssl' gem 'mime-types', ['~> 2.6', '< 2.99'] + if ENV['RAILS_VERSION'] == 'edge' gem 'railties', :github => 'rails/rails' + elsif ENV['RAILS_VERSION'] + gem 'railties', "~> #{ENV['RAILS_VERSION']}" else - gem 'railties', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 5.2']) + gem 'railties', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 6.2']) end end @@ -29,15 +48,29 @@ group :test do if ENV['RAILS_VERSION'] == 'edge' gem 'actionmailer', :github => 'rails/rails' gem 'activerecord', :github => 'rails/rails' + elsif ENV['RAILS_VERSION'] + gem 'actionmailer', "~> #{ENV['RAILS_VERSION']}" + gem 'activerecord', "~> #{ENV['RAILS_VERSION']}" else - gem 'actionmailer', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 5.2']) - gem 'activerecord', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 5.2']) + gem 'actionmailer', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 6.2']) + gem 'activerecord', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 6.2']) end - - gem 'coveralls', :require => false + gem 'net-smtp' if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.1.0') gem 'rspec', '>= 3' + gem 'simplecov', :require => false + if /\A2.[12]/ =~ RUBY_VERSION + # 0.8.0 doesn't work with simplecov < 0.18.0 and older ruby can't run 0.18.0 + gem 'simplecov-lcov', '< 0.8.0', :require => false + else + gem 'simplecov-lcov', :require => false + end + if ENV['RAILS_VERSION'].nil? || ENV['RAILS_VERSION'] >= '6.0.0' + gem 'zeitwerk', :require => false + end +end + +group :rubocop do gem 'rubocop', '>= 0.25', '< 0.49' - gem 'simplecov', '>= 0.9' end gemspec diff --git a/README.md b/README.md index 893cb8f7a..ff7f2660b 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,16 @@ **If you're viewing this at https://github.com/collectiveidea/delayed_job, you're reading the documentation for the master branch. [View documentation for the latest release -(4.1.4).](https://github.com/collectiveidea/delayed_job/tree/v4.1.4)** +(4.1.11).](https://github.com/collectiveidea/delayed_job/tree/v4.1.11)** Delayed::Job ============ -[![Gem Version](https://badge.fury.io/rb/delayed_job.png)][gem] -[![Build Status](https://travis-ci.org/collectiveidea/delayed_job.png?branch=master)][travis] -[![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job.png?travis)][gemnasium] -[![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job.png)][codeclimate] -[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job/badge.png?branch=master)][coveralls] +[![Gem Version](https://badge.fury.io/rb/delayed_job.svg)][gem] +![CI](https://github.com/collectiveidea/delayed_job/workflows/CI/badge.svg) +[![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job.svg)][codeclimate] +[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job/badge.svg?branch=master)][coveralls] [gem]: https://rubygems.org/gems/delayed_job -[travis]: https://travis-ci.org/collectiveidea/delayed_job -[gemnasium]: https://gemnasium.com/collectiveidea/delayed_job [codeclimate]: https://codeclimate.com/github/collectiveidea/delayed_job [coveralls]: https://coveralls.io/r/collectiveidea/delayed_job @@ -62,16 +59,16 @@ running the following command: rails generate delayed_job:active_record rake db:migrate -For Rails 4.2, see [below](#rails-42) +For Rails 4.2+, see [below](#active-job) Development =========== In development mode, if you are using Rails 3.1+, your application code will automatically reload every 100 jobs or when the queue finishes. You no longer need to restart Delayed Job every time you update your code in development. -Rails 4.2 -========= -Set the queue_adapter in config/application.rb +Active Job +========== +In Rails 4.2+, set the queue_adapter in config/application.rb ```ruby config.active_job.queue_adapter = :delayed_job @@ -170,9 +167,10 @@ end If you ever want to call a `handle_asynchronously`'d method without Delayed Job, for instance while debugging something at the console, just add `_without_delay` to the method name. For instance, if your original method was `foo`, then call `foo_without_delay`. -Rails 3 Mailers -=============== -Due to how mailers are implemented in Rails 3, we had to do a little work around to get delayed_job to work. +Rails Mailers +============= +Delayed Job uses special syntax for Rails Mailers. +Do not call the `.deliver` method when using `.delay`. ```ruby # without delayed_job @@ -181,12 +179,16 @@ Notifier.signup(@user).deliver # with delayed_job Notifier.delay.signup(@user) -# with delayed_job running at a specific time +# delayed_job running at a specific time Notifier.delay(run_at: 5.minutes.from_now).signup(@user) + +# when using parameters, the .with method must be called before the .delay method +Notifier.with(foo: 1, bar: 2).delay.signup(@user) ``` -Remove the `.deliver` method to make it work. It's not ideal, but it's the best -we could do for now. +You may also wish to consider using +[Active Job with Action Mailer](https://edgeguides.rubyonrails.org/active_job_basics.html#action-mailer) +which provides convenient `.deliver_later` syntax that forwards to Delayed Job under-the-hood. Named Queues ============ @@ -377,6 +379,9 @@ Hooks ===== You can define hooks on your job that will be called at different stages in the process: + +**NOTE:** If you are using ActiveJob these hooks are **not** available to your jobs. You will need to use ActiveJob's callbacks. You can find details here https://guides.rubyonrails.org/active_job_basics.html#callbacks + ```ruby class ParanoidNewsletterJob < NewsletterJob def enqueue(job) @@ -430,7 +435,7 @@ end On error, the job is scheduled again in 5 seconds + N ** 4, where N is the number of attempts or using the job's defined `reschedule_at` method. -The default `Worker.max_attempts` is 25. After this, the job either deleted (default), or left in the database with "failed_at" set. +The default `Worker.max_attempts` is 25. After this, the job is either deleted (default), or left in the database with "failed_at" set. With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours. The default `Worker.max_run_time` is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to diff --git a/delayed_job.gemspec b/delayed_job.gemspec index 75f014a2f..bfa4305ed 100644 --- a/delayed_job.gemspec +++ b/delayed_job.gemspec @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |spec| - spec.add_dependency 'activesupport', ['>= 3.0', '< 6.1'] + spec.add_dependency 'activesupport', ['>= 3.0', '< 6.2'] spec.authors = ['Brandon Keepers', 'Brian Ryckbost', 'Chris Gaffney', 'David Genord II', 'Erik Michaels-Ober', 'Matt Griffin', 'Steve Richert', 'Tobias Lütke'] spec.description = 'Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.' spec.email = ['brian@collectiveidea.com'] @@ -13,5 +13,10 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] spec.summary = 'Database-backed asynchronous priority queue system -- Extracted from Shopify' spec.test_files = Dir.glob('spec/**/*') - spec.version = '4.1.4' + spec.version = '4.1.11' + spec.metadata = { + 'changelog_uri' => 'https://github.com/collectiveidea/delayed_job/blob/master/CHANGELOG.md', + 'bug_tracker_uri' => 'https://github.com/collectiveidea/delayed_job/issues', + 'source_code_uri' => 'https://github.com/collectiveidea/delayed_job' + } end diff --git a/lib/delayed/backend/base.rb b/lib/delayed/backend/base.rb index c8bb09835..d18fd4270 100644 --- a/lib/delayed/backend/base.rb +++ b/lib/delayed/backend/base.rb @@ -148,7 +148,8 @@ def destroy_failed_jobs? end def fail! - update_attributes(:failed_at => self.class.db_time_now) + self.failed_at = self.class.db_time_now + save! end protected diff --git a/lib/delayed/backend/shared_spec.rb b/lib/delayed/backend/shared_spec.rb index 771e0cd9c..39f497670 100644 --- a/lib/delayed/backend/shared_spec.rb +++ b/lib/delayed/backend/shared_spec.rb @@ -523,7 +523,8 @@ def create_job(opts = {}) it 'reloads changed attributes' do story = Story.create(:text => 'hello') job = story.delay.tell - story.update_attributes :text => 'goodbye' + story.text = 'goodbye' + story.save! expect(job.reload.payload_object.object.text).to eq('goodbye') end diff --git a/lib/delayed/psych_ext.rb b/lib/delayed/psych_ext.rb index 8cd941907..00350a453 100644 --- a/lib/delayed/psych_ext.rb +++ b/lib/delayed/psych_ext.rb @@ -28,7 +28,13 @@ def self.create end def visit_Psych_Nodes_Mapping(object) # rubocop:disable CyclomaticComplexity, MethodName, PerceivedComplexity - return revive(Psych.load_tags[object.tag], object) if Psych.load_tags[object.tag] + klass = Psych.load_tags[object.tag] + if klass + # Implementation changed here https://github.com/ruby/psych/commit/2c644e184192975b261a81f486a04defa3172b3f + # load_tags used to have class values, now the values are strings + klass = resolve_class(klass) if klass.is_a?(String) + return revive(klass, object) + end case object.tag when %r{^!ruby/object} diff --git a/lib/delayed/railtie.rb b/lib/delayed/railtie.rb index 0249ea0f9..a50ca1b4b 100644 --- a/lib/delayed/railtie.rb +++ b/lib/delayed/railtie.rb @@ -4,10 +4,6 @@ module Delayed class Railtie < Rails::Railtie initializer :after_initialize do - ActiveSupport.on_load(:action_mailer) do - ActionMailer::Base.extend(Delayed::DelayMail) - end - Delayed::Worker.logger ||= if defined?(Rails) Rails.logger elsif defined?(RAILS_DEFAULT_LOGGER) diff --git a/lib/delayed/worker.rb b/lib/delayed/worker.rb index af7855d39..0c6981f8e 100644 --- a/lib/delayed/worker.rb +++ b/lib/delayed/worker.rb @@ -1,5 +1,6 @@ require 'timeout' require 'active_support/dependencies' +require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/numeric/time' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/hash_with_indifferent_access' @@ -260,7 +261,7 @@ def reschedule(job, time = nil) job.unlock job.save! else - job_say job, "REMOVED permanently because of #{job.attempts} consecutive failures", 'error' + job_say job, "FAILED permanently because of #{job.attempts} consecutive failures", 'error' failed(job) end end diff --git a/lib/delayed_job.rb b/lib/delayed_job.rb index 439dd8587..d38f2edbc 100644 --- a/lib/delayed_job.rb +++ b/lib/delayed_job.rb @@ -3,12 +3,6 @@ require 'delayed/exceptions' require 'delayed/message_sending' require 'delayed/performable_method' - -if defined?(ActionMailer) - require 'action_mailer/version' - require 'delayed/performable_mailer' -end - require 'delayed/yaml_ext' require 'delayed/lifecycle' require 'delayed/plugin' @@ -19,5 +13,15 @@ require 'delayed/deserialization_error' require 'delayed/railtie' if defined?(Rails::Railtie) +ActiveSupport.on_load(:action_mailer) do + require 'delayed/performable_mailer' + ActionMailer::Base.extend(Delayed::DelayMail) + ActionMailer::Parameterized::Mailer.include(Delayed::DelayMail) if defined?(ActionMailer::Parameterized::Mailer) +end + +module Delayed + autoload :PerformableMailer, 'delayed/performable_mailer' +end + Object.send(:include, Delayed::MessageSending) Module.send(:include, Delayed::MessageSendingClassMethods) diff --git a/spec/delayed/backend/test.rb b/spec/delayed/backend/test.rb index 28031171f..6835a7b49 100644 --- a/spec/delayed/backend/test.rb +++ b/spec/delayed/backend/test.rb @@ -87,11 +87,6 @@ def self.db_time_now Time.current end - def update_attributes(attrs = {}) - attrs.each { |k, v| send(:"#{k}=", v) } - save - end - def destroy self.class.all.delete(self) end diff --git a/spec/helper.rb b/spec/helper.rb index d33ea7f5d..0ba9657e6 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -1,20 +1,25 @@ require 'simplecov' -require 'coveralls' +require 'simplecov-lcov' -SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter] +SimpleCov::Formatter::LcovFormatter.config do |c| + c.report_with_single_file = true + c.single_report_path = 'coverage/lcov.info' +end +SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new( + [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter + ] +) SimpleCov.start do add_filter '/spec/' - # Each version of ruby and version of rails test different things - # This should probably just be removed. - minimum_coverage(85.0) end require 'logger' require 'rspec' require 'action_mailer' -require 'active_support/dependencies' require 'active_record' require 'delayed_job' @@ -42,11 +47,21 @@ def self.root Delayed::Worker.backend = :test -# Add this directory so the ActiveSupport autoloading works -ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__) +if ActiveSupport::VERSION::MAJOR < 7 + require 'active_support/dependencies' -# Add this to simulate Railtie initializer being executed -ActionMailer::Base.extend(Delayed::DelayMail) + # Add this directory so the ActiveSupport autoloading works + ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__) +else + # Rails 7 dropped classic dependency auto-loading. This does a basic + # zeitwerk setup to test against zeitwerk directly as the Rails zeitwerk + # setup is intertwined in the application boot process. + require 'zeitwerk' + + loader = Zeitwerk::Loader.new + loader.push_dir File.dirname(__FILE__) + loader.setup +end # Used to test interactions between DJ and an ORM ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:' diff --git a/spec/performable_mailer_spec.rb b/spec/performable_mailer_spec.rb index 72e5e2068..39796eea2 100644 --- a/spec/performable_mailer_spec.rb +++ b/spec/performable_mailer_spec.rb @@ -1,6 +1,5 @@ require 'helper' -require 'action_mailer' class MyMailer < ActionMailer::Base def signup(email) mail :to => email, :subject => 'Delaying Emails', :from => 'delayedjob@example.com', :body => 'Delaying Emails Body' @@ -41,3 +40,29 @@ def signup(email) end end end + +if defined?(ActionMailer::Parameterized::Mailer) + describe ActionMailer::Parameterized::Mailer do + describe 'delay' do + it 'enqueues a PerformableEmail job' do + expect do + job = MyMailer.with(:foo => 1, :bar => 2).delay.signup('john@example.com') + expect(job.payload_object.class).to eq(Delayed::PerformableMailer) + expect(job.payload_object.object.class).to eq(ActionMailer::Parameterized::Mailer) + expect(job.payload_object.object.instance_variable_get('@mailer')).to eq(MyMailer) + expect(job.payload_object.object.instance_variable_get('@params')).to eq(:foo => 1, :bar => 2) + expect(job.payload_object.method_name).to eq(:signup) + expect(job.payload_object.args).to eq(['john@example.com']) + end.to change { Delayed::Job.count }.by(1) + end + end + + describe 'delay on a mail object' do + it 'raises an exception' do + expect do + MyMailer.with(:foo => 1, :bar => 2).signup('john@example.com').delay + end.to raise_error(RuntimeError) + end + end + end +end diff --git a/spec/psych_ext_spec.rb b/spec/psych_ext_spec.rb index 86cc7391c..82e67aef4 100644 --- a/spec/psych_ext_spec.rb +++ b/spec/psych_ext_spec.rb @@ -3,10 +3,32 @@ describe 'Psych::Visitors::ToRuby', :if => defined?(Psych::Visitors::ToRuby) do context BigDecimal do it 'deserializes correctly' do - deserialized = YAML.load("--- !ruby/object:BigDecimal 18:0.1337E2\n...\n") + deserialized = YAML.load_dj("--- !ruby/object:BigDecimal 18:0.1337E2\n...\n") expect(deserialized).to be_an_instance_of(BigDecimal) expect(deserialized).to eq(BigDecimal('13.37')) end end + + context 'load_tag handling' do + # This only broadly works in ruby 2.0 but will cleanly work through load_dj + # here because this class is so simple it only touches our extention + YAML.load_tags['!ruby/object:RenamedClass'] = SimpleJob + # This is how ruby 2.1 and newer works throughout the yaml handling + YAML.load_tags['!ruby/object:RenamedString'] = 'SimpleJob' + + it 'deserializes class tag' do + deserialized = YAML.load_dj("--- !ruby/object:RenamedClass\ncheck: 12\n") + + expect(deserialized).to be_an_instance_of(SimpleJob) + expect(deserialized.instance_variable_get(:@check)).to eq(12) + end + + it 'deserializes string tag' do + deserialized = YAML.load_dj("--- !ruby/object:RenamedString\ncheck: 12\n") + + expect(deserialized).to be_an_instance_of(SimpleJob) + expect(deserialized.instance_variable_get(:@check)).to eq(12) + end + end end diff --git a/spec/yaml_ext_spec.rb b/spec/yaml_ext_spec.rb index aebb9afce..83bceea35 100644 --- a/spec/yaml_ext_spec.rb +++ b/spec/yaml_ext_spec.rb @@ -25,7 +25,7 @@ it 'autoloads the class of an anonymous struct' do expect do yaml = "--- !ruby/struct\nn: 1\n" - object = YAML.load(yaml) + object = load_with_delayed_visitor(yaml) expect(object).to be_kind_of(Struct) expect(object.n).to eq(1) end.not_to raise_error