开发者

Old Ruby bug is recurring in my Ruby on Rails app, related to Class.create and delayed_job

The bug is many months old, here:

http://www.ruby-forum.com/topic/1094002

Two links in that which show code changes:

https://github.com/godfat/ruby/commit/f4e0e8f781b05c767ad2472a43a4ed0727a75708 https://github.com/godfat/ruby/commit/c7a6cf975d88828c2ed27d253f41c480f9b66ad6

I have Ruby 1.9.2 and rvm. I would have pasted those changes into the appropriate files, but I don't know how.

This worked a few days ago. I can't do Ruby on Rails commands like:

>> User.create :username => "a", :password => "a"

Here is the error message:

ArgumentError: wrong number of arguments(1 for 0)
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `method'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2 p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `accept'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:36:in `<<'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych.rb:165:in `dump'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/core_ext.rb:13:in `psych_to_yaml'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/backend/base.rb:57:in `payload_object='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2918:in `block in assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `each'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2787:in `attributes='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2477:in `initialize'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `new'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `create'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/message_sending.rb:9:in `method_missing'
from /Users/RedApple/S/app/models/user.rb:29:in `block in <class:User>'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-2.3.14/lib/active_support/callbacks.rb:182:in `call'
... 7 levels...
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:267:in `create_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2927:in `create_or_update'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:250:in `create_or_update_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2577:in `save'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/validations.rb:1089:in `save_with_validation'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p2开发者_StackOverflow90/gems/activerecord-2.3.14/lib/active_record/dirty.rb:79:in `save_with_dirty'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:229:in `block in with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:182:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `block in save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:727:in `create'
from (irb):1
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'>

Line 28-30 in user.rb:

after_create do |user|
  user.delay( :priority => -15 ).seed
end

I am dead in the water without this. Can anyone help?


Delayed Job and the Ruby 1.9.2 YAML parser (Psych) are unfortunately not compatible.

Switch back to the previous YAML parser (Syck) by adding this to your config/application.rb, just below the call to Bundler.require:

YAML::ENGINE.yamler = "syck" if RUBY_VERSION >= "1.9.2"


You could patch your Ruby, but it's not easy and not really possible on managed hosts. My solution was to create a monkeypatch based on the patch commit 31075.

Create an initializer file in your Rails project config/initializers/psych_extensions.rb and add this code:

# APPLIES RUBY PATCH REVISION 31075

module Psych
  module Visitors
    ###
    # YAMLTree builds a YAML ast given a ruby object.  For example:
    #
    #   builder = Psych::Visitors::YAMLTree.new
    #   builder << { :foo => 'bar' }
    #   builder.tree # => #<Psych::Nodes::Stream .. }
    #
    class YAMLTree < Psych::Visitors::Visitor

      def accept target
        # return any aliases we find
        if node = @st[target.object_id]
          node.anchor = target.object_id.to_s
          return @emitter.alias target.object_id.to_s
        end

        if target.respond_to?(:to_yaml)
          loc = target.public_method(:to_yaml).source_location.first
          if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
            unless target.respond_to?(:encode_with)
              if $VERBOSE
                warn "implementing to_yaml is deprecated, please implement \"encode_with\""
              end

              target.to_yaml(:nodump => true)
            end
          end
        end

        if target.respond_to?(:encode_with)
          dump_coder target
        else
          send(@dispatch_cache[target.class], target)
        end
      end

      private

      # FIXME: remove this method once "to_yaml_properties" is removed
      def find_ivars target
        loc = target.public_method(:to_yaml_properties).source_location.first
        unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb')
          if $VERBOSE
            warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\""
          end
          return target.to_yaml_properties
        end

        target.instance_variables
      end

    end
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜