How to load javascript file from rails plugin - ruby-on-rails

I'm trying to create a plugin which is suppose to expose a javascript file, but I can't get it to load in my rails 5 application.
In my gem, I've tried adding my javascript file called my_gem.js to
vendor/assets/javascripts
app/assets/javascripts
lib/<gem-name>/assets/javascripts
But none of them work. I just get this error message when loading the file in my application.js
couldn't find file 'my_gem' with type 'application/javascript'
This is how I load my plugin/gem in to my rails project
gem "my-gem", path: "~/projects/my-gem"

We've created a gem which utilizes assets before.
You'll want to create an app/assets/javascripts/my_gem folder in your gem directory tree, where you'll put your my_gem.js file.
Most importantly, you need to add this file to the asset path (we use an engine):
#lib/my_gem.rb
module MyGem
class Gem < Rails::Engine
config.assets.precompile += %w(my_gem/my_gem.js)
end
end
This will either allow the file to be used standalone, or as part of your app:
#app/assets/javascripts/application.js
//= require my_gem/my_gem

You must tell Rails to compile my_gem.js. You can do this in an initializer, application.rb, or environment file.
Rails.application.config.assets.precompile += ["my_gem.js"]
I'd recommend keeping the source file at ~/projects/my-gem/app/assets/javascripts/my_gem.js

Related

Heroku does not load assets from asset pipeline

In my Rails app I have css and js that is unique to each action.
So users#new has its own css. It's named users_new.css.scss.
I deployed my app to Heroku, and Heroku isn't loading any of the assets. You can see the errors here. How do I fix this so Heroku correctly precompiles and loads the assets?
I read through Heroku's docs on using the asset pipeline, but didn't see any solution.
Precompilation
The problem is your timelines_index.js is not precompiled:
The way you can tell this is a problem is that when you call the asset in your layout (which I presume you're doing with the correct path helpers), Rails will automatically reference the latest precompiled version of that file (hence why application.js has the appended MD5 fingerprint)
I believe you'll need to add your custom files to your precompiled_assets array:
#config/environments/production.rb
Rails.application.config.assets.precompile += ['timelines_index.js']
This will give Rails the ability to precompile those assets individually, allowing you to call them in your layout:
#app/views/layouts/application.html.erb
<%= javascript_include_tag "timelines_index" %>
This will have to be done for all the custom asset files you wish to call in your layout.
Manifest
As mentioned by Anil, you may wish to use the manifest system of Rails to concatenate all your asset files into their respective application files.
This will quash the need to append the files to the Rails precompile array, allowing you to call a single file for your various assets:
#app/assets/javascripts/application.js
//= require_tree .
Add in your Gemfile
gem 'rails_12factor', group: :production

How to use typeahead.js as a Bower component with Rails 4

I'm trying to use typeahead.js in my Rails 4 app. I would like to use Bower to do this instead of using the gem. I have installed it in vendor/assets/components. I have also included the line below in config/application.rb.
config.assets.paths << Rails.root.join('vendor', 'assets', 'components')
I have searched extensively but cannot seem to figure out what exactly I should include in app/assets/javascripts/application.js to get Rails to recognize this. The directory typeahead.js is installed properly in vendor/assets/components. I have tried
//= require typeahead.js
as well a few other options but it's not working. I'm a relative newbie to Rails and am still trying to figure out how some of the things work under the hood. Any help is appreciated.
I would recommend that instead you use Rails Assets. Getting started is as simple as adding
source 'https://rails-assets.org' do
gem 'rails-assets-bootstrap' #example
gem 'rails-assets-angular' #example
gem 'rails-assets-leaflet' #example
end
to your Gemfile, replacing the examples with bower assets you need. Simply prefix a given Bower asset with "rails-assets-", and you're good to go.
Be sure to check out their website if you need any help getting started!
Your bower.json file should specify a "typeahead" dependency like this:
"vendor": {
"name": "bower-rails generated vendor assets",
"dependencies": {
"typeahead": "git#github.com:twitter/typeahead.js.git"
}
}
Run rake bower:install, it should place the library in vendor/assets/bower_components
Then in your application.js
//= require typeahead
I did not use typeahead.js after I posted my question, but need to use it now and got it to work. First of all I didn't need to add anything to config/application.rb since the vendor/assets directory is already included in the asset pipeline.
Bower installed the directory typeahead.js in the vendor/assets/components directory as I put
{
"directory": "vendor/assets/components"
}
in my .bowerrc file.
And in my app/assets/javascripts/application.js I include the full path to the typeahead.jquery.min.js file:
//= require typeahead.js/dist/typeahead.jquery.min.js
Everything works fine now.

How to read files (.yml) from a Gem

I want to read a .yml file included in a Rails Engine Gem from my main_app. The file is located at config/test.yml.
IO.read("config/test.yml") fails with No such file or directory # rb_sysopen
If i move the file into the main app, everything works fine. But i need this file in a Gem.
Solution 1
You can store the root path in a constant from your main gem file and retrieve it in other locations of your code. You must ensure that the gem got initialized before the code in your app runs otherwise you'll have an errors because the constant won't be defined.
# lib/my_gem.rb
GEM_ROOT = File.expand_path("../..", __FILE__)
# app/.../some_class.rb
IO.read("#{GEM_ROOT}/config/test.yml")
Solution 2
The most advisable, you can get the gem path programmatically from Bundler, then use that root path to retrieve the full path of your yml file.
Have a look at this answer that you can easily adapt to your case
You should be able to load app yaml files by doing this in your gem:
YAML.load_file('config/test.yml')

How do you instruct Sprockets to include files from /vendors/assets/components on Heroku?

I want to manage clientside assets using Bower which installs resources such as angular into
/vendors/assets/components/angular/angular.js
I reference these assets in the application.css.scss file as follows:
/* ...
*= require bootstrap
*/
However while this works ok for development and the files are included ok, they're not getting picked up by sprockets for compilation in production on Heroku.
How can I instruct Sprockets to pick up and compile files from /vendor/assets/components/?
You should be able to tell the pipeline to include extra directories like this:
config.assets.paths << Rails.root.join('vendor', 'assets', 'components')
You may also need to tell it to precompile specific files too, as only the main application.js & application.css are precompiled by default:
config.assets.precompile << %w( frontpage.css frontpage.js *.svg )
With Rails 4 on Heroku you need to add the 12factorapp gem
Finally, if you are using Heroku then for Rails 4 you'll need to add the following Gem
group :production do
gem 'rails_12factor'
end
See this question for more information

Loading compiled bootstrap into rails withot any gem

What is the cleanest way to import twitter-bootstrap into rails without any gem?
So far I've been manually copying the css/js files into vendor/assets/javascripts, vendor/assets/stylesheets
Is there a way to do this without moving the files into separate folders?
You could all CSS and JS in vendor/assets/twitter-bootstrap.
Then in app/assets/javascripts/application.js:
//=require_tree ../../../vendor/assets/twitter-bootstrap
And in your app/assets/stylesheets/application.css:
*= require ../../../vendor/assets/twitter-bootstrap
For non JS or CSS assets like images to go in non-standard directory, in either config/application.rb or environment-specific config, you'd use:
# can add more than one path string or regexp(s)
config.assets.precompile += ['../../../vendor/assets/twitter-bootstrap/*.png']
The recommended way is to either use a well-maintained gem for your assets, or continue to put vendor JS and CSS assets in vendor/assets/javascripts and vendor/assets/stylesheets, respectively.
I copied bootstrap into lib/bootstrap
I'm using make bootstrap to compile it, then running a rake task to copy the compiled files into vendor/assets
require 'fileutils'
task :bootme do
compiled_bootstrap = 'lib/bootstrap/bootstrap'
FileUtils.cp_r(compiled_bootstrap + '/css/.', 'vendor/assets/stylesheets/')
FileUtils.cp_r(compiled_bootstrap + '/img/.', 'vendor/assets/images/')
FileUtils.cp_r(compiled_bootstrap + '/js/.', 'vendor/assets/javascripts/')
end

Resources