Forum: Ruby on Rails Can't get an Array function to be visible inside ApplicationHelper

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
skt (Guest)
on 2009-04-12 06:53
(Received via mailing list)
Folks,

I seem to be missing something basic here.

I am trying to call a function from my application layout that will
return me a hash of the roles for the user currently signed in. Here
is the simplified code I have in ApplicationHelper module

  class Array
    def to_h
      Hash[*enum_with_index.to_a.flatten]
    end
  end

  def get_cur_user_roles
    ["school_admin", "General2"].to_h
  end

I call get_cur_user_roles from my layout file. When I bring up the web
page I get an error that says

undefined method `to_h' for ["school_admin", "General2"]:Array

However, if I capture the same code in a test.rb file (adding a
require 'enumerator' at the top of the file for the enum_with_index
function) and run it with "ruby test.rb" it seems to work fine.

Any thoughts on why the code above is not seeing the Array instance
method to_h in the ApplicaitonHelper? I also tried changing it to
class method by changing the declaration to self.to_h but get the same
error. Somehow the to_h method is not visible to the ["school_admin",
"General2"] Array and I don't understand why. I have tried restarting
the server but get the same error.

Thanks for help/pointers.

-S
Frederick C. (Guest)
on 2009-04-12 11:53
(Received via mailing list)
On Apr 12, 3:52 am, skt <removed_email_address@domain.invalid> wrote:
>       Hash[*enum_with_index.to_a.flatten]
> undefined method `to_h' for ["school_admin", "General2"]:Array
> the server but get the same error.
>

Because you write that inside the ApplicationHelper module, this is
creating a new ApplicationHelper::Array class with those 2 methods. In
you test.rb it's not nested in a module. If you wrote your array
extensions outside of the module you shouldn't have this problem.
(Personally I would put extensions to core classes in files in lib/
and require them from initializers rather than dumping them in
ApplicationHelper. I would also be wary of adding too many quite
specialised methods to Array.

Fred
Sj T. (Guest)
on 2009-04-12 21:37
> Because you write that inside the ApplicationHelper module, this is
> creating a new ApplicationHelper::Array class with those 2 methods. In
> you test.rb it's not nested in a module. If you wrote your array
> extensions outside of the module you shouldn't have this problem.
> (Personally I would put extensions to core classes in files in lib/
> and require them from initializers rather than dumping them in
> ApplicationHelper. I would also be wary of adding too many quite
> specialized methods to Array.


Fred - I agree with the points you make about having a separate file in
lib and being careful about adding too many specialized functions to
core classes like Array. However I am not very clear on why adding a
method to Array class inside ApplicationHelper module creates a new
ApplicationHelper::Array class as opposed to opening the existing core
Array class and adding the to_h method to it. As I understood it, you
could open a class anywhere and add methods to it. Sounds like there are
caveats to this that I am not very clear on - would appreciate your help
in clarifying that.

Thanks,
-S
Frederick C. (Guest)
on 2009-04-12 23:25
(Received via mailing list)
On 12 Apr 2009, at 18:37, Sj Tib wrote:

>
> caveats to this that I am not very clear on - would appreciate your
> help
> in clarifying that.
>

You can reopen a class from anywhere. The way modules & scoping work
in ruby means

module Foo
   class Bar
   end
end

defines a new Foo::Bar class (and it's important that you can do this,
so that you can namespace your classes without trampling on other
stuff).

If you wanting this to instead refer to the top level Bar class then
you can write ::Bar, or in your case ::Array.


Fred
Sj T. (Guest)
on 2009-04-13 11:17
>
> If you wanting this to instead refer to the top level Bar class then
> you can write ::Bar, or in your case ::Array.
>

Thanks Fred - that was very helpful.
This topic is locked and can not be replied to.