Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

undefined method `length' for Enumerable when calling truncate method

#867

Hello, this seems to be a small bug in text_helpers truncate method. When trying to call e.g. truncate('Hello World!', 5, '...') it generates following error:

undefined method length' for #<Enumerable::Enumerator:0x243a7a4>

Full trace:


#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb:44:in `truncate'
#{RAILS_ROOT}/app/views/admin/posts/post_list.rhtml:25:in `_run_rhtml_47app47views47admin47posts47post_list46rhtml'
#{RAILS_ROOT}/app/views/admin/posts/post_list.rhtml:22:in `each'
#{RAILS_ROOT}/app/views/admin/posts/post_list.rhtml:22:in `_run_rhtml_47app47views47admin47posts47post_list46rhtml'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_view/base.rb:326:in `send'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_view/base.rb:326:in `compile_and_render_template'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_view/base.rb:301:in `render_template'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_view/base.rb:260:in `__render_file'
#{RAILS_ROOT}/vendor/plugins/theme_support/lib/patches/actionview_ex.rb:44:in `render_file'
#{RAILS_ROOT}/vendor/plugins/theme_support/lib/patches/actionview_ex.rb:24:in `each'
#{RAILS_ROOT}/vendor/plugins/theme_support/lib/patches/actionview_ex.rb:24:in `render_file'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:806:in `render_file'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:741:in `render_with_no_layout'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/layout.rb:244:in `render_without_benchmark'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:50:in `render'
/opt/local/lib/ruby/1.8/benchmark.rb:293:in `measure'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:50:in `render'
#{RAILS_ROOT}/app/controllers/admin/posts_controller.rb:48:in `post_list'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:1095:in `send'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:1095:in `perform_action_without_filters'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:632:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:638:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:438:in `call'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:637:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:638:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:438:in `call'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:637:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:638:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:438:in `call'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:637:in `call_filter'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:619:in `perform_action_without_benchmark'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'
/opt/local/lib/ruby/1.8/benchmark.rb:293:in `measure'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/rescue.rb:83:in `perform_action'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:430:in `send'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:430:in `process_without_filters'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/filters.rb:624:in `process_without_session_management_support'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/session_management.rb:114:in `process'
#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/base.rb:330:in `process'
#{RAILS_ROOT}/vendor/rails/railties/lib/dispatcher.rb:41:in `dispatch'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:76:in `process'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `synchronize'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `process'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:282:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `each'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/command.rb:212:in `run'
/opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281

It seems changing method to


def truncate(text, length = 30, truncate_string = "...")
  if text
    l = length - truncate_string.chars.to_a.length
    chars = text.chars
    (chars.to_a.length > length ? chars.to_a[0...l].to_s + truncate_string : text).to_s
  end
end

will solve the problem.

My configuration is following: OS: Mac OS X 10.5, Rails: rails 2.1.0, Ruby: ruby 1.8.7, Application server: mongrel 1.1.5

Reported by Gregor Magdolen · August 20th, 2008 @ 01:16 AM

State: resolved
Milestone: 2.x
Assigned to: Michael Koziarski Michael Koziarski
Importance: none

Activity

  1. Peter Wagenet
    Peter Wagenet

    If your fix works, make a patch with some tests to verify it. If you don't know where to start, check out: http://rails.lighthouseapp.com/p...

    August 23rd, 2008 @ 07:20 PM

  2. Ronald de Gunst
    Ronald de Gunst

    truncate takes an option hash instead of separate length and omission arguments See http://www.rubyonrails.org/depre... for details.

    August 23rd, 2008 @ 10:44 PM

  3. Gregor Magdolen
    Gregor Magdolen

    @peter: thanks, im new to ruby and rails and i found bug by "accident", but i'll try my best to make a patch.

    @ronald: can you be more specific? I can't find enough information on site you provided. I also believe I have installed latest stable release of rails (installed via gem)

    August 23rd, 2008 @ 11:11 PM

  4. Peter Wagenet
    Peter Wagenet

    Gregor, it seems we often run into these sorts of things by accident :) Good luck with the patch. I can take a look at it for you once you get it up. Let me know if you have any difficulties.

    August 24th, 2008 @ 01:53 AM

  5. Boo Yah
    Boo Yah

    Peter, I ran into the same issue but solved the problem by eliminating the calls to the 'chars' function:

    
    def truncate(text, length = 30, truncate_string = "...")
      if text.nil? then return end
      l = length - truncate_string.length
      (text.length > length ? text[0...l] + truncate_string : text).to_s
    end
    

    September 28th, 2008 @ 06:08 AM

  6. Peter Wagenet
    Peter Wagenet

    @Boo Yah: You'll want to make sure that's the right solution. The chars method is for dealing with Unicode, so removing that call may make the truncate method no longer Unicode safe.

    September 28th, 2008 @ 04:32 PM

  7. tigris
    tigris

    Gregor,

    The issue is that 1.8.7 ruby introduced it's own chars() method onto the String object, overwriting ActiveSupport's attempts to patch it's own chars() method on there.

    I believe if you roll back to ruby 1.8.6, your problem will go away.

    I am unsure if it is fixed in newer versions of rails, I am about to go and update my rails now and make sure it all works on 1.8.6 before I attempt to upgrade ruby again.

    regards, Danial

    September 30th, 2008 @ 07:25 AM

  8. tigris
    tigris

    Edit: looks fixed in current rails

    http://github.com/rails/rails/co...

    09/21/08: Change all calls to String#chars to String#mb_chars.

    September 30th, 2008 @ 07:35 AM

  9. iGEL
    iGEL
    • Tag changed from actionpack, bug, enumerable, helper to actionpack, activesupport, bug, enumerable, helper, multibyte

    I can verify this problem. "Hello".chars is returning an Enumerable::Enumerator on Rails 2.2 RC1 and 2 with ruby 1.8.7. With Rails 2.1.2/Ruby 1.8.7 it worked fine.

    Using Ubuntu 8.10 here.

    "Hello".chars.downcase NoMethodError: undefined method downcase' for #<Enumerable::Enumerator:0xb6809e84>

    November 15th, 2008 @ 11:21 PM

  10. iGEL
    iGEL

    After 2 hours of searching for a bug in Rails, I've realized, that I've should have read tigris completely. Sorry...

    November 16th, 2008 @ 12:12 AM

  11. DHH
    DHH
    • Assigned user set to Michael Koziarski

    November 16th, 2008 @ 08:42 PM

  12. Michael Koziarski
    Michael Koziarski
    • State changed from new to resolved

    2.1.x doesn't support ruby 1.8.7.

    Either downgrade to 1.8.6 or upgrade rails to 2.2 RC2

    November 17th, 2008 @ 01:29 PM

  13. Nathan de Vries
    Nathan de Vries

    Can this not be solved (albeit hackishly) by dropping the following into an initializer?

    
    class String
      def chars
        ActiveSupport::Multibyte::Chars.new(self)
      end
      alias_method :mb_chars, :chars
    end
    

    I'm using that trick to get Mephisto + Rails v2.0.5 running under 1.8.7.

    November 25th, 2008 @ 07:11 AM

  14. Micah Wedemeyer
    Micah Wedemeyer

    Nathan, I could kiss you. Your little snippet was enough to get me up and running while I search for a way to migrate a legacy app to something new.

    November 2nd, 2009 @ 10:16 AM