Using rake task to generate these javascript files is really an option. I'm using rake tasks to generate i18n translation files for JS frontend from translation files in YAML format. One option is to use ERB for templates. I'd put rakefile under lib/tasks/foo.rake
and templates under lib/tasks/foo/foo.erb
. If your JS template is not very complex, i'd suggest using plain Hash.to_json
method to generate javascript contents:
namespace :js do
task :generate_config => :environment do
File.open("#{RAILS_ROOT}/public/javascripts/configuration.js", 'w') do |out|
config = {:option_1 => 'Value 1', :option_2 => 'Value 2'}
out << "var CONFIG = #{config.to_json}"
end
end
end
But configuration files are something you just don't want to forget to be regenerated when your configuration source data has been changed. I'm using a solution to generate "minified" JS files on production environment to append huge number of javascript files together so i can save on HTTP requests. But you can use basically the same solution. It works great if you use Capistrano to deploy your application.
In file app/helpers/application_helper.rb
create new helper method which is available globally:
module ApplicationHelper
def javascript_include_config_tag
if ActionController::Base.perform_caching
unless File.exists?("#{RAILS_ROOT}/public/javascripts/configuration.js")
#
# TODO: Generate configuration data in here
#
config = 'configuration file contents'
File.open("#{RAILS_ROOT}/public/javascripts/configuration.js", 'w') do |out|
out << config
end
end
javascript_include_tag('configuration')
else
# Link to js generated dynamically on each request. Useful in development.
javascript_include_tag('PATH_TO_DYNAMICALLY_GENERATED_JS')
end
end
end
And in your view you just include javascript with
<%= javascript_include_config_tag %>
The idea here is that this JS configuration file is being generated only first time on page load after fresh Capistrano deploy. It also has a huge downside that you cannot request configuration.js
file before first page generate, but in my app, it works fine so far.