Can we move the "helpers" folder to "views/helpers"?

Hi everyone,

I know this would break a long-standing tradition, but I really think the “app/helpers” folder should really by “app/views/helpers”.

I think it helps communicate that any methods in there are intended primarily for the views to use.

I’m not sure how big a job it would be to make this change, but I’m ready to investigate if the core team agrees that this would be something nice for Rails 4.

Thanks!

Jeff

If, for whatever reason, it makes sense to have a HelpersController in your app, now you have a name clash and have to work around it.

IMHO there’s nothing wrong with app/helpers per se. If you think the problem is a lack of documentation, that would be the place to improve :slight_smile:

Cheers,

-foca

Historically, helpers can be and have been included in controllers by some, as they are modules. As you said, “any methods in there are intended primarily for the views”- primarily being the operative word. I would think moving them would hurt more than it would help. In addition, right now autoloading works under the premise that everything under the autoloaded directory has the same fully-qualified path to the constant as the relative path under one of the autoload directories. So, you’d then want to add complexity to that to say when autoloading, ensure that if there is another autoloaded directory under that directory, then ignore that directory when autoloading the higher level autoloaded directory. That would get too messy. The alternative would mean adding a Helpers module for each helper which would be cumbersome and break things.

So, you’d then want to add complexity to that to say when autoloading, ensure that if there is another autoloaded directory under that directory, then ignore that directory when autoloading the higher level autoloaded directory.

Sorry, wasn’t thinking. Since the constants would be loaded in a prior autoload path, it wouldn’t attempt to load them again. I’ll try to be helpful:

In config/application.rb, you’d just:

config.autoload_paths += %W(#{config.root}/app/views/helpers)

if you want to remove the old autoload dir then also add:

config.eager_load_paths -= %W(#{config.root}/app/helpers)

then at command-line:

mkdir app/views/helpers mv app/helpers/* app/views/helpers/ rmdir app/helpers

then:

rails c

and autoload_paths is the first of the autoload paths evaluated you can see from evaluating:

MyRailsApp::Application._all_autoload_paths

But, Rails generators and any other gems that create helpers may expect the app/helpers path to exist, be writable, and/or be autoloaded.

So, you could symlink app/helpers to app/views/helpers or remove app/helpers and then do pull requests for gems/etc. as they break.

You could also suggest making each of the autoload paths configurable in Rails, but, like I said, you’d have compatibility issues with gems that mod or read files in autoloaded dirs like annotate, modelist, etc. so probably a no-go.

Some more reasons that you would not want to remove app/helpers from load path. In Rails 3.2.9, here are the hardcoded usages of that path, so even though Rails console loads, it could break elsewhere in addition to just the generators:

grep -r “app/helpers” * | grep -v “_test.rb|_tests.rb|README|USAGE”

actionpack/lib/action_controller/metal/helpers.rb: # Extract helper names from files in app/helpers/**/_helper.rb railties/guides/source/command_line.textile: Helper: app/helpers/credit_card_helper.rb railties/guides/source/command_line.textile: Helper: app/helpers/admin/credit_card_helper.rb railties/guides/source/command_line.textile: create app/helpers/greetings_helper.rb railties/guides/source/command_line.textile: exists app/helpers/ railties/guides/source/command_line.textile: create app/helpers/high_scores_helper.rb railties/guides/source/command_line.textile: create app/helpers railties/guides/source/command_line.textile: create app/helpers/application_helper.rb railties/guides/source/configuring.textile:+prepend_helpers_path+* Adds the directory +app/helpers+ from the application, railties and engines to the lookup path for helpers for the application. railties/guides/source/engines.textile:create app/helpers/blorgh/posts_helper.rb railties/guides/source/engines.textile:create app/helpers/blorgh/comments_helper.rb railties/guides/source/generators.textile: create app/helpers/users_helper.rb railties/guides/source/generators.textile: create_file “app/helpers/#{file_name}_helper.rb”, <<-FILE railties/guides/source/generators.textile:And it will generate the following helper file in +app/helpers+: railties/guides/source/generators.textile: create app/helpers/posts_helper.rb railties/guides/source/generators.textile: create_file “app/helpers/#{file_name}_helper.rb”, <<-FILE railties/guides/source/generators.textile: create app/helpers/comments_helper.rb railties/guides/source/getting_started.textile:|app/helpers/posts_helper.rb |Helper functions to be used from the post views| railties/guides/source/getting_started.textile:| app/helpers/comments_helper.rb | A view helper file | railties/guides/source/getting_started.textile:View Helpers live in app/helpers and provide small snippets of reusable railties/guides/source/getting_started.textile:Open up app/helpers/posts_helper.rb and add the following: railties/lib/rails/engine/configuration.rb: paths.add “app/helpers”, :eager_load => true railties/lib/rails/engine.rb: # paths[“app/helpers”] # => [“app/helpers”] railties/lib/rails/engine.rb: paths[“app/helpers”].existent railties/lib/rails/engine.rb: app.config.helpers_paths.unshift(*paths[“app/helpers”].existent) railties/lib/rails/generators/rails/helper/helper_generator.rb: template ‘helper.rb’, File.join(‘app/helpers’, class_path, “#{file_name}_helper.rb”) railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb: empty_directory_with_gitkeep “app/helpers” railties/lib/rails/tasks/statistics.rake: %w(Helpers app/helpers),