Dynelight
Dynelight

Reputation: 2162

Nested Helpers Issue

I'm trying to migrate a legacy app from 3 to 4 (and of course I'll go to 5 and 6 next). Basically it is a helper heavy app, and it encapsulates a lot of the logic on helpers.

I have some trouble loading helpers on rails 4 and I think I sorted it out but I seem to be having issues with nested helpers. I'm using the traceroute gem to validate that the routes on the routes.rb work properly and I'm coming with some issues there.

Example:

uninitialized constant Permissions
/home/app/helpers/permissions/charts_helper.rb:1:in `<top (required)>'

Charts helper (app/helpers/permissions/charts_helper.rb)

module Permissions::ChartsHelper

  ...

end

Importing of helpers on application.rb:

   config.autoload_paths << Rails.root.join('lib')
   # config.autoload_paths += Dir["#{config.root}/app/helpers/**/"]
   Dir["#{config.root}/app/models/concerns/**/*.rb"].each { |file| require file[0..-4]}
   Dir["#{config.root}/app/helpers/**/*.rb"].each { |file| require file[0..-4]}

(I had to comment out the second line in favor of the 4th line and it seemed to import some helpers but not all)

So basically I'm looking for:

1.) Best way to include these helpers on the applications.rb file 2.) Make the helpers work 3.) Any best practices or other advice that can help me move forward.

Upvotes: 1

Views: 338

Answers (1)

max
max

Reputation: 102194

module Permissions
  module ChartsHelper
    # ...
  end
end

Define (and reopen) namespaced classes and modules using explicit nesting. Using the scope resolution operator can lead to surprising constant lookups due to Ruby’s lexical scoping, which depends on the module nesting at the point of definition.
- the Ruby Style Guide

Using :: is not a shorthand for explicit nesting and it requires that Permissions be loaded first to avoid a missing constant error.

module Permissions::ChartsHelper
end
# NameError (uninitialized constant Permissions)

It also sets the wrong module nesting:

FOO = "I'm in the global scope"

module Permissions
  FOO = "I'm Permissions::FOO"
end

module Permissions::ChartsHelper
  puts FOO # I'm in the global scope
  puts Module.nesting.inspect # [Permissions::ChartsHelper]
end

In Ruby only the module and class keywords change the current module nesting. By contrast if you explicitly nest the modules:

FOO = "I'm in the global scope"

module Permissions
  FOO = "I'm Permissions::FOO"
end

module Permissions
  module ChartsHelper
    puts FOO # I'm Permissions::FOO
    puts Module.nesting.inspect # [Permissions::ChartsHelper, Permissions]
  end
end

Upvotes: 2

Related Questions