Can't get an Array function to be visible inside ApplicationHelper

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

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.

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

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.

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

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.