In a rails 3.2 app, I would like to check for the existence of a javascript file in the asset pipeline before including the javascript_include_tag in a file. Something like:
<% if javascript_file_exists? %>
<%= javascript_include_tag "#{controller_name}_controller" %>
<% end %>
I would like to do this so that the absence of a javascript file will not result in an error. Is there a way to do this?
A more Rails way is to use a helper. This allows you to check for a coffeescript or a javascript version of a file:
def javascript_exists?(script)
script = "#{Rails.root}/app/assets/javascripts/#{params[:controller]}.js"
File.exists?(script) || File.exists?("#{script}.coffee")
end
Then you can use it in your layout:
<%= javascript_include_tag params[:controller], :media => "all" if javascript_exists?(params[:controller]) %>
You can do the same with your CSS:
-- helper --
def stylesheet_exists?(stylesheet)
stylesheet = "#{Rails.root}/app/assets/stylesheets/#{params[:controller]}.css"
File.exists?(stylesheet) || File.exists?("#{stylesheet}.scss")
end
-- layout --
<%= stylesheet_link_tag params[:controller], :media => "all" if stylesheet_exists?(params[:controller]) %>
EDIT: updated #javascript_exists?
I have recently made some changes to my javascript_exists?
helper:
def javascript_exists?(script)
script = "#{Rails.root}/app/assets/javascripts/#{script}.js"
extensions = %w(.coffee .erb .coffee.erb) + [""]
extensions.inject(false) do |truth, extension|
truth || File.exists?("#{script}#{extension}")
end
end
call it in the application layout:
<%= javascript_include_tag params[:controller] if javascript_exists?(params[:controller]) %>
This will now handle more extensions and use an inject to determine if the file exists. You can then add a bunch more extensions to the extensions array, as needed for your app.
EDIT DEUX: Updated #stylesheet_exists?
Same, but for stylesheets:
def stylesheet_exists?(stylesheet)
stylesheet = "#{Rails.root}/app/assets/stylesheets/#{stylesheet}.css"
extensions = %w(.scss .erb .scss.erb) + [""]
extensions.inject(false) do |truth, extension|
truth || File.exists?("#{stylesheet}#{extension}")
end
end
EDIT Last (probably): DRY it up
def asset_exists?(subdirectory, filename)
File.exists?(File.join(Rails.root, 'app', 'assets', subdirectory, filename))
end
def image_exists?(image)
asset_exists?('images', image)
end
def javascript_exists?(script)
extensions = %w(.coffee .erb .coffee.erb) + [""]
extensions.inject(false) do |truth, extension|
truth || asset_exists?('javascripts', "#{script}.js#{extension}")
end
end
def stylesheet_exists?(stylesheet)
extensions = %w(.scss .erb .scss.erb) + [""]
extensions.inject(false) do |truth, extension|
truth || asset_exists?('stylesheets', "#{stylesheet}.css#{extension}")
end
end
Although I know about the assets pipeline and the manifest in application.js, my approach is to keep app's "essential" javascript in application.js and load only the specific javascript for each controller using
<%= javascript_include_tag "application" %>
<%= javascript_include_tag controller_name if File.exists?("#{Rails.root}/app/assets/javascripts/#{controller_name}.js") %>
at the end of my application.html.erb before the </body>
I know that causes the browser to issue one more request to get the controller specific javascript but perhaps after the first request, that javascript will be cached by the browser.
I know this is a pretty old question, but I would suggest using the find_asset function. For Rails 4 you could do something like:
<%= javascript_include_tag params[:controller] if ::Rails.application.assets.find_asset("#{params[:controller]}.js") %>
Add this to your ApplicationHelper
:
module ApplicationHelper
def controller_stylesheet(opts = { media: :all })
if Rails.application.assets.find_asset("#{controller_name}.css")
stylesheet_link_tag(controller_name, opts)
end
end
def controller_javascript(opts = {})
if Rails.application.assets.find_asset("#{controller_name}.js")
javascript_include_tag(controller_name, opts)
end
end
end
and you can use them like this in your application.html.erb
:
<%= controller_stylesheet %>
<%= controller_javascript %>
Note: This works with all .js, .coffee, .css, .scss even though it just says .css and .js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With