This project is archived and is in readonly mode.

#5657 ✓resolved
Andrew C. Greenberg

[PATCH] Rails 3.0 console hard aborts on attempted autocompletion in Ruby 1.8.7, and prints inappropriate deprecation notice in Ruby 1.9.2

Reported by Andrew C. Greenberg | September 18th, 2010 @ 07:40 PM

The rails console aborts on attempted irb autocompletion of a partial expression. Try the following from any rails 3.0 project

rails c
Loading development environment (Rails 3.0.0)
ree-1.8.7-2010.02 > Time.now.

After typing the period, hit escape. Boom! A bizarre error message

this module is deprecated, please use the PREDICATES constant

is produced, irb aborts, and the terminal is left in a peculiar state. The attached patch repairs this problem, which arises from some crufty "deprecation" notices in Arel.

Discussion:

IRB autocompletion makes a valiant effort to obtain the class of a partial expression when the value is not known, which involves a fair amount of introspection on the overall state of the present environment. Unsurprisingly, it makes considerable use of the #instance_methods method on various classes -- well all the classes it can find to be true. Here lies the problem. Part of its pruning entails calling #sort! on the array of results it obtains. This is where it blows up in the rails environment.

It turns out that there is a class in Arel, called Predications, that overrides #instance_methods, but instead of returning an array of Strings, as Class and its progeny do, Arel::Attribute::Predications.method_missing returns an array of Symbols. And an array of symbols does not like to be sorted, since symbols do not respond to "<=>". Boom!

Predications is defined as follows in lib/arel/algebra/attributes/attribute.rb

    PREDICATES = [
      :eq, :eq_any, :eq_all, :not_eq, :not_eq_any, :not_eq_all, :lt, :lt_any,
      :lt_all, :lteq, :lteq_any, :lteq_all, :gt, :gt_any, :gt_all, :gteq,
      :gteq_any, :gteq_all, :matches, :matches_any, :matches_all, :not_matches,
      :not_matches_any, :not_matches_all, :in, :in_any, :in_all, :not_in,
      :not_in_any, :not_in_all
    ]

    Predications = Class.new do
      def self.instance_methods *args
        warn "this module is deprecated, please use the PREDICATES constant"
        PREDICATES
      end
    end

The first commit in the patch repairs the blow-up by returning PREDICATES.map(:&to_s). I also presumed to change the logger warning into one using Rails ActiveSupport::Deprecation, so that the message is routed approporiately.

This worked so far as it went, and the console no longer blew up. However, it continues to print the deprecation message each and every time you try to autocomplete a partial expression in the Rails console (or any other app that requires Arel for that matter).

Inspecting the file's git history, it appeared that this section of code historically appeared like the following:

module Predications

   def eq
   ...
   end
   ... other definitions ...
end
include Predications

During the Arel speedup en route to Rails 3.0, much of the metaprogramming and including and such was removed, including the references to module Predications. At one point it was deleted completely, and then later added back as a class, rather than as a module as shown above. I didn't see any point to the vestigial structure being permitted to continue to exist while destroying my beloved rails console, and rewrote it as a module with the corrected #instance_methods, without the deprecation warning there, and adding a deprecation warning upon inclusion, using "#included." That was the second commit referred to in the patch.

The resulting code passes the test suite (using Sqlite only, i didn't have the heart to build the mysql and postgress environments just to include this patch) and some new ones added to highlight the problem.

Now my autocompleting life has returned and I am a little bit happier. Thought I would share the ponies and rainbows with my favorite community. Hope I have done more good than harm.

Comments and changes to this ticket

  • Andrew C. Greenberg

    Andrew C. Greenberg September 18th, 2010 @ 11:28 PM

    • Title changed from “Rails 3.0 console hard aborts on attempted autocompletion [PATCH supplied]” to “[PATCH] Rails 3.0 console hard aborts on attempted autocompletion”
  • Brian Candler

    Brian Candler September 20th, 2010 @ 11:32 AM

    but instead of returning an array of Strings, as Class and its progeny do, Arel::Attribute::Predications.method_missing returns an array of Symbols

    Unfortunately, this depends on which Ruby version you are using.

    $ ruby -e 'p String.instance_methods[0,5]'
    ["%", "select", "[]=", "inspect", "<<"]
    $ ruby19 -e 'p String.instance_methods[0,5]'
    [:<=>, :==, :eql?, :hash, :casecmp]
    

    And an array of symbols does not like to be sorted, since symbols do not respond to "<=>". Boom!

    Similarly:

    $ ruby -e 'p [:foo, :bar].sort'
    -e:1:in `sort': undefined method `<=>' for :foo:Symbol (NoMethodError)
            from -e:1
    $ ruby19 -e 'p [:foo, :bar].sort'
    [:bar, :foo]
    

    However, even in 1.9 you can't mix Symbol and String in a sort:

    $ ruby19 -e 'p [:foo, "bar"].sort'
    -e:1:in `sort': comparison of Symbol with String failed (ArgumentError)
            from -e:1:in `<main>'
    

    So I think you should map PREDICATES to strings only if RUBY_VERSION < "1.9"

  • Andrew C. Greenberg

    Andrew C. Greenberg September 21st, 2010 @ 10:36 PM

    A useful observation, and it may explain how this wasn't caught earlier. Even so, the deprecation notice is still routinely printed in the rails console for expression autoompletion, and that should be fixed. Accordingly, I added a test to catch the ruby version dependence, added your suggested change, and included the previous changes to remove the version dependence.

    In retrospect, it seems to me that using the array and override of #instance_methods is a brittle hack in the original. A better method might have been simply to metaprogam all the methods into the module (adding the dep warnings for the use of the procedure, not the introspection), and let the respective rubies determine how they would report the list of methods. Rather than do that, I leave it to the arel community to explain what functionality or purpose Predications still has, if any. If it is totally vestigial, perhaps the existing stuff is good enough.

    Anyway, I attach a patch that repairs the repair so it works now with 1.8.7 and 1.9.2, AND eliminates the random deprecation messages in the ruby console hsving no relation to the autocompletion.

  • Andrew C. Greenberg

    Andrew C. Greenberg September 21st, 2010 @ 10:36 PM

    • Title changed from “[PATCH] Rails 3.0 console hard aborts on attempted autocompletion” to “[PATCH] Rails 3.0 console hard aborts on attempted autocompletion in Ruby 1.8.7, and prints inappropriate deprecation notice in Ruby 1.9.2”
  • Andrew C. Greenberg
  • Andrew C. Greenberg

    Andrew C. Greenberg September 21st, 2010 @ 10:38 PM

    • Tag changed from arel console to arel, console
  • Ryan Bigg

    Ryan Bigg September 30th, 2010 @ 06:51 AM

    • Importance changed from “” to “Low”

    Your patch does not apply to the rails/arel repository because the files it modifies are no longer there. Please update it to reflect this.

  • Ryan Bigg

    Ryan Bigg September 30th, 2010 @ 06:53 AM

    I cannot reproduce this on Rails master.

  • Ben Mills

    Ben Mills September 30th, 2010 @ 07:12 AM

    • Assigned user set to “Ryan Bigg”

    Not reproducible on Rails master

  • Ryan Bigg

    Ryan Bigg September 30th, 2010 @ 07:12 AM

    • State changed from “new” to “resolved”
    • Assigned user cleared.

    Confirmed fixed in master.

  • Stephen Davis

    Stephen Davis November 14th, 2010 @ 09:38 PM

    This issue is still present in Rails 3.0.1

    
    $ rails -v
    Rails 3.0.1
    $ ruby -v
    ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
    $ rails new testapp ; cd testapp
    $ rails c
    Loading development environment (Rails 3.0.1)
    irb(main):001:0> Time.now.
    

    press tab to autocomplete here, and you get

    
    this module is deprecated, please use the PREDICATES constant
    /usr/lib/ruby/1.8/irb/completion.rb:162:in `sort!': undefined method `<=>' for :not_in_all:Symbol (NoMethodError)
        from /usr/lib/ruby/1.8/irb/completion.rb:162
        from /usr/lib/ruby/1.8/irb/input-method.rb:97:in `call'
        from /usr/lib/ruby/1.8/irb/input-method.rb:97:in `readline'
        from /usr/lib/ruby/1.8/irb/input-method.rb:97:in `gets'
        from /usr/lib/ruby/1.8/irb.rb:140
        from /usr/lib/ruby/1.8/irb.rb:271:in `signal_status'
        from /usr/lib/ruby/1.8/irb.rb:139
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:189:in `call'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:189:in `buf_input'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:104:in `getc'
        from /usr/lib/ruby/1.8/irb/slex.rb:206:in `match_io'
        from /usr/lib/ruby/1.8/irb/slex.rb:76:in `match'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:287:in `token'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:263:in `lex'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:234:in `each_top_level_statement'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `loop'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `catch'
        from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
        from /usr/lib/ruby/1.8/irb.rb:154:in `eval_input'
        from /usr/lib/ruby/1.8/irb.rb:71:in `start'
        from /usr/lib/ruby/1.8/irb.rb:70:in `catch'
        from /usr/lib/ruby/1.8/irb.rb:70:in `start'
        from /usr/lib/ruby/gems/1.8/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
        from /usr/lib/ruby/gems/1.8/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
        from /usr/lib/ruby/gems/1.8/gems/railties-3.0.1/lib/rails/commands.rb:23
        from script/rails:6:in `require'
        from script/rails:6
    

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Tags

Pages