Issue with Javascript include in Rails app - ruby-on-rails

I'm using Rails 3.2.8. When the app is deployed access the view that is including a javascript:
<%= javascript_include_tag "epiceditor" %>
Heroku fails with this log:
ActionView::Template::Error (/app/app/assets/javascripts/epiceditor.js.erb has already been required
I've checked some possible solutions, like checking for any reference that may trigger a circular dependency, or simply removing it in case it is being included somewhere else, which isn't. So, if I include it, I get this "has already been included error", if I don't , then the file isn't included at all.
My config/application.rg has this
config.assets.initialize_on_precompile = false
And applications.js has this:
//= require jquery
//= require jquery_ujs
//= require tabs
It might be important to note that the file the tag is referencing is "epiceditor.js.erb", since it has some embedded Rails code that I needed.
Thanks for your help
EDIT:
I believe this is a bug in Sprockets. If I update Rails to 3.2.9rc2, the error is now this:
ActionView::Template::Error (Asset logical path has no extension: epiceditor/.js
but of course the extension in epiceditor is epiceditor.js.erb, and I've tried being explicit about it in the javascript_include_tag as well.

I found the bug.
It turns out that inside the .js.erb file I'm calling
<% asset_path 'epiceditor/' %>
which should expand to the path where all the epiceditor file are placed, but instead is actually loading the file itself in recursive manner. This is expanding properly in the development environment but not in the production environment. Funny, right?
The reason for this is that is adding a digest. So I fixed the whole issue with this:
<%= asset_path 'epiceditor/', :digest => false %>
and now it does expand to the directory, and doesn't fall into the recursion trap.
Hope this saves some time for someone!

Related

#= require not working after upgrade to Rails 5

I upgraded Rails 4.2.10 application to Rails 5. Solved errors with bundling and some deprecations. I am able to start the Rails Application, but when I try to load the Application, it fails with error, Invalid CSS after "#": expected id name, was "= require in the css file
I tried using #import, but it fails for external files in vendor/assets. Nevertheless, I want to understand why it isnt working anymore. In my config, I have the file in config.assets.precompile +=
In my index.html.erb,
<%= stylesheet_link_tag 'users' %>
In users.scss,
#= require "dashboard/dx"
Note: I am using sass-rails in my Gemfile
The error that I get,
Sass::SyntaxError in Dashboard::Users#index
Invalid CSS after "#": expected id name, was "= require "dash..."
Extracted source (around line #1):
#= require "dashboard/dx"
Hey I think the error is throwing because in your typical .scss file you would have to use either an #import "dashboard/dx" and#= requiremight only work in.css`
The problem with this line
#= require "dashboard/dx"
This syntax is not working with .scss file. Either You have to write like this
#import 'dashboard/dx'
Or rename the file with .css extension.
Note: You can also try to rename with .css.scss extension May be it works also sometimes.

Rails precompile multiple javascript_includes_tag

I'm actually building a new app under Rails 4.
I used to put my javascript_includes_tag at the bottom of my layout. But for an unknown reason, it creates a bug when trying to use confirm: on delete link.
So I put back this line at the top :
!!!
%html{ :lang => 'en' }
%head
= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true
= javascript_include_tag "application", "data-turbolinks-track" => true
So far so good, the bug is now gone. Anyway, since my app is gonna use a lot of Javascript, I still need to load those third part library at the bottom. So, what I did is to only let the Rails library at the top :
// application.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
Then I tried to create another js file named third-part and try to do the same as application but including my third part libraries. Unfortunately, it does not work.
// third-part.js
//= require bootstrap
//= require app
//= require app.plugin
How can I add another javascript_includes_tag at the bottom the same way I did for application? Here I mean that on production it will also compress those files.
Thanks a lot for your help
EDIT :
It's actually loading my files well on DEVELOPMENT, but not on my production.
On production I just got <script data-turbolinks-track="true" src="/javascripts/third-part.js"></script> and I can't access the file
I've tried :
config.assets.precompile += %w( third-part.js )
and
rake assets:precompile RAILS_ENV=production
but it still not working
EDIT 2 :
I made a test of precompliling on production mode from my local machine. It did work. It might be a problem with my server.
EDIT 3 :
Just earse my application from server and clone a new one from my Github but it's still not working. Don't know why :(
In your config/environments/production.rb add this line to precompile the external assets
config.assets.precompile += ["third-part.js"]
and don't forget to mention env=production while precompiling assets on production.

How do I prevent an asset from being cached by the Rails Asset Pipeline in development mode?

I added a custom engine for HAML in config/initializers.
When I visit http://127.0.0.1:3000/assets/page.html it renders the page successfully.
# page.html.haml
!!! 5
%html{:lang => "en"}
%head
= stylesheet_link_tag 'application'
= javascript_include_tag 'application'
The problem is Rails seems to cache the html asset. When I add or remove a file from the application.js manifest it doesn't update until I stop the Rails server and run rake tmp:clear. An alternative is to touch the application.js file. I have config.assets.debug = true set because I prefer to see individual files/folders in Chrome DevTools rather than one big application.js file.
Is there a way to exclude certain assets from being cached during development.
Just to reiterate - its the HTML being cached which is the problem, changes to the manifest are reflected when visiting http://127.0.0.1:3000/assets/application.js.
A brute force solution would be to add some depends_on attributes to the haml file:
# page.html.haml
#= depend_on application.js
#= depend_on application.css
!!! 5
%html{:lang => "en"}
%head
= stylesheet_link_tag 'application'
= javascript_include_tag 'application'
This should force the asset to be regenerated when the application.js file is changed.
There are a few cavets with this. The file names should be the names in the source tree. It assumes you can use # for comments in your HAML renderer (I don't know HAML so I'm not sure).I'm also not really sure how this works with a custom engine. Also, a better solution would be to have your custom HAML engine track dependencies itself, but I don't know how to do this.
See the sprockets docs for more details

Include Assets Only If They Exist

In our current rails app, we are following certain patterns for including assets such as scripts and stylesheets.
For instance, one such pattern is (code inside the layout):
= stylesheet_link_tag controller.controller_name
The problem here is that not all of the controllers are going to have associated stylesheets. What is the best way to check if an asset exists? Specifically, I know there is some trickery here due to the cache busting asset names.
Finally figured this one out. Asset existence can be checked as follows:
YourApp::Application.assets.find_asset("#{asset}.css").nil?
The answer would then be:
= stylesheet_link_tag controller.controller_name if YourApp::Application.assets.find_asset("#{controller.controller_name}.css")
I had found this answer before and we'd been happily using find_asset in our application (Rails 3.2.16), until one day it started bombing out.
After some digging, it turns out that even in a production environment, with asset precompilation enabled, the first call to find_asset will attempt to actually compile the asset it's looking for, even if that asset has been precompiled already. As you can imagine, this is not good news -- in our specific case, we were pulling in a Compass library file into a stylesheet, which worked in dev and during precompile, but not in production, where Compass was not in the assets load path.
Long story short, find_asset is not a bulletproof way to determine if an asset is available to include. You can read a bunch more about it in the issue someone tried to file about this, and which was subsequently closed as not a bug: https://github.com/sstephenson/sprockets/issues/411
The real way to determine if an asset exists, and which works in both compile and precompile modes is demonstrated in the hoops that the filer of the above issues needed to jump through. Here's the diff for his fix: https://github.com/fphilipe/premailer-rails/pull/55/files
I'm putting this here in hopes that other Googlers who find this don't fall into the same trap I did!
To include an asset based on controller name
<% controller_asset = controller.controller_name %>
<%= stylesheet_link_tag controller_asset if YourApp::Application.assets.find_asset(controller_asset) %>
To include an asset based on controller name and action name (was useful for me)
<% action_asset = "#{controller.controller_name}/#{controller.action_name}" %>
<%= stylesheet_link_tag action_asset if YourApp::Application.assets.find_asset(action_asset) %>
And of course it'd be better not to leave this code as it is, but rather place it in a helper.
= stylesheet_link_tag controller.controller_name if File.exists?(File.join(Rails.public_path, 'assets', "#{controller.controller_name}.css"))
Simple ViewHelpers
This is what I use myself. Add this to your ApplicationHelper:
module ApplicationHelper
def controller_stylesheet(opts = { media: :all })
if Rails.application.assets.find_asset("#{params[:controller]}.css")
stylesheet_link_tag(params[:controller], opts)
end
end
def controller_javascript(opts = {})
if Rails.application.assets.find_asset("#{params[:controller]}.js")
javascript_include_tag(params[:controller], opts)
end
end
end
and use them like this in your application.html.haml:
= controller_stylesheet
= controller_javascript
Note: This works with all .js, .coffee, .css, .scss even though it just says .css and .js

Asset Pipeline Cacheing CSS?

I am working on a Rails 3.1 app. I have created an application.css.scss.erb file. The .erb is in the end because I want to load a variable from the config file as the color variable in the css:
$highlight1: #<%= COLOR.highlight1 %>;
$highlight2: #<%= COLOR.highlight2 %>;
Everything works fine, but the problem I am having is that whenever I change a value inside COLOR.highlight1, it doesn't reflect the change until I go in to my css file and change something (i usually add some spaces and save it). Thats when I see the change. Clearly rails is looking to see if the file was changed in order to update the change.
Is there any way that at least during development, this can be turned off and I can see the changes without having to also modify the css file?
Any critique/opinions on my technique are also welcome
The Sprockets depend_on directive is used to declare these kinds of dependencies. So at the top of your css.scss.erb file, with the other directives (require and friends), put something like:
//= depend_on "/path/to/colors.rb"
Then when the file /path/to/colors.rb changes, it will force the css to update too.
Unfortunately, I have never gotten this to work with a relative path to a file outside of one of the asset directories (javascripts/stylesheets/images) so there may be something in the way Sprockets resolves paths that prevents this, or else I'm missing something. That leaves you with the options of specifying an absolute path, which will almost certainly not work in across all your app environments, or putting the constants file into your asset directories (app/assets/stylesheets/colors.rb, for example).
For reference, here's the doc for the depend_on directive from the Sprockets (2.0.3) source, in sprockets/directive_processor.rb
# Allows you to state a dependency on a file without
# including it.
#
# This is used for caching purposes. Any changes made to
# the dependency file will invalidate the cache of the
# source file.
#
# This is useful if you are using ERB and File.read to pull
# in contents from another file.
#
# //= depend_on "foo.png"
#
If anyone does know a way to specify relative paths to other places like config/initializers or something, please let me know!
In addition to David Faber's answer. I needed to use relative paths too.
I wanted to generate a js file with the locale dictionary, which would update if the locale files were changed:
//= depend_on "../../../config/locales/en.yml"
//= depend_on "../../../config/locales/ja.yml"
var locales = <%= locales.to_json %>;
Turns out that currently (Rails 3.2.3) relative paths only work if the relative path is also in the assets path!
So the ugly solution is to add the path in config/application.rb:
config.assets.paths.unshift Rails.root.join("config", "locales").to_s
http://guides.rubyonrails.org/configuring.html
config.assets.compile is a boolean that can be used to turn on live Sprockets compilation in production.
might want to try that, I'm not sure if its getting compiled real time though, at least it should disable the caching.
maybe try:
config.assets.digest = true
in your development config file
I try this, it work
in application.rb
config.autoload_paths += %W(#{config.root}/lib/assets_variables)
config.assets.paths << File.join(Rails.root, 'lib', 'assets_variables')
in lib/assets_variables/color.rb
module Color
def self.default
'blue'
end
end
in app/assets/stylesheets/color.css.scss.erb
//= depend_on "color.rb"
$default_color: <%= Color::default %>;
.content {
color: $default_color;
}

Resources