My libraries are not being loaded on production - ruby-on-rails

Everything works fine locally.
In my application.rb :
module Maestra
class Application < Rails::Application
config.autoload_paths += Dir["#{config.root}/lib/MyLib/**/"]
Then I deploy, and in console MyLib is an undefined class.
So if I change my application.rb to :
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Then MyLib is a known class but it has no namespaces nor methods.
My directories are set up as so :
+ Lib
+ MyLib
MyLib.gemspec
+ lib
common.rb
my_custom_namespace.rb
So on my local I can very easily do : MyLib::MyCustomNamespace, but remotely, with the latter config in my application.rb, that namespace does not exist.

Related

How to precompile a pdf asset in Rails?

In Rails 3.2.11 app I'm trying to publish my app to Heroku.
In the assets folder I have a pdf subfolder with some pdf files inside.
In my production.rb file I have added the following:
config.assets.precompile += %w[*.png *.jpg *.jpeg *.gif *.pdf]
config.assets.precompile += ["*.js"]
config.assets.precompile += ["*.css"]
config.assets.precompile += ['pdf/*']
config.assets.precompile += %w( ricerca_wg.pdf )
If I check the pdf assets paths on my console I get:
Rails.application.config.assets.paths
# [
# "/Users/Augusto/Sites/wisegrowth/app/assets/images",
# "/Users/Augusto/Sites/wisegrowth/app/assets/javascripts",
# "/Users/Augusto/Sites/wisegrowth/app/assets/pdf",
# "/Users/Augusto/Sites/wisegrowth/app/assets/stylesheets",
# "/Users/Augusto/Sites/wisegrowth/vendor/assets/javascripts",
# "/Users/Augusto/Sites/wisegrowth/vendor/assets/stylesheets",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/jquery-rails-2.3.0/vendor/assets/javascripts",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/coffee-rails-3.2.2/lib/assets/javascripts",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/formtastic-2.1.1/app/assets/stylesheets"
# ]
But when I run
rake assets:precompile RAILS_ENV=production
everything is precompiled BUT the pdf files and in my production app on Heroku I get the following error:
ActionView::Template::Error (ricerca_wg.pdf isn't precompiled):
I don't think a pdf must be "precompiled".
if you just want to access the pdf from your app without using another service like S3, you can just put that pdf folder on your public folder of the rails app, and they will be available on the app as an static file.
www.domain.com/pdf/ricerca_wg.pdf
just be sure that the public/pdf folder isn't in the gitignore and it must work.
I believe the ricerca_wg.pdf is under /Users/Augusto/Sites/wisegrowth/app/assets/pdf/? If not, simply
remove config.assets.precompile += %w( ricerca_wg.pdf )
move ricerca_wg.pdf under /Users/Augusto/Sites/wisegrowth/app/assets/pdf/ - it should be precompiled along with other pdf files from this directory

RoR autoload sub directories

I have created a "services" dir in app/ where I have created some classes (services). Now it's looks like this :
-app
-services
-class1
-class2
-class3
-class4
For now, I have added app/services in config/spring.rb
%w(
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
app/services
app/errors
).each { |path| Spring.watch(path) }
So my classes in services are loaded.
But now, I want to do this :
-app
-services
-dir1
-class1
-class2
-dir2
-class3
-class4
I got error :
uninitialized constant TransactionService::AuthorizeRequest
How autoload a dir and subdir ?
Rails tries to guess namespaces by dirnames & filenames. So, to have a TransactionService::AuthorizeRequest class name, you should have the exact following structure:
app
- services
-- transaction_service
--- authorize_request.rb
Your class sould looks like :
module TransactionService
class AuthorizeRequest
end
end

Rails same file name for different classes

Having model Price (models/price.rb)
class Price
end
Also in lib directory I have import/detector/price.rb file
class Import::Detector::Price
end
Lib directory added to autoload paths via
config.autoload_paths += Dir["#{config.root}/lib/**/"]
So running Price.new I get error
Unable to autoload constant Price, expected lib/import/detector/price.rb to define it.
Import::Detector::Price.new is ok
What was my mistake?
UPD.
The most interesting
Also having this file models/car/property/price.rb
class Car::Property::Price
end
And everything ok with it. Car::Property::Price is available.
Try
config.autoload_paths += Dir["#{config.root}/lib"]
instead of
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Using **, Dir will return every directory under lib and will put them all (as root directories) in the load path. It should only be the main lib directory in the load path as rails will work out the subdirectories using the namespace.
Rails autoloading — how it works, and when it doesn't

Rails - how to load the whole directory of files in /lib?

I have in the lib directory following structure:
/lib/dir_a/dir_b/dir_c/
In dir_c are stored images.
I am trying to load these images and display them in views. I have tried to set up the path to the images in views, but I got the 404 error.
So I did following: created a file in the initializers folder and into this file I put:
Dir[Rails.root + 'lib/dir_a'].each do |file|
require file
end
For loading all content stored in the dir_a directory (which involves as subdirectories as files).
But when I restarted server, I got this error:
...dependencies.rb:251:in `require': cannot load such file -- /Users/radek/rubydev/EDI/lib/brands (LoadError)
I also tried stuff like
Dir[Rails.root + 'lib/dir_a/'].each do |file|
or
Dir[Rails.root + 'lib/dir_a/**'].each do |file|
But none of those helped me.
Thus, is there any way to load a content from /lib directory and work with them in views?
Dir[Rails.root + 'lib/**/*.rb'].each do |file|
require file
end

How do I use config.assets.precompile for directories rather than single files?

How do I use config.assets.precompile in production to only include the files in 'lib/assets/javascripts', 'lib/assets/stylesheets', 'vendor/assets/javascripts' and 'vendor/assets/stylesheets'?
Basically something like:
config.assets.precompile += %w( pagespecific.js anotherpage.js )
But used to auto include files in specific directories that are not 'app/assets/javascripts' or 'app/assets/stylesheets'.
*edit: adding the solution I ended up using for page specific js
config.assets.precompile += ['pages/*.js']
You can simply write it like this:
config.assets.precompile += ['directory/*']
The point of compiling assets is to build one (or a small number of) files to minimize the number of HTTP requests from the browser.
If you're going to serve each file individually, then why not just disable precompile?
To use precompile as intended, build an entire directory into one file using Sprockets' require_directory:
//= require_directory ./awesome_js_app
...and list that file in your config.assets.precompile array.
By default, all CSS is built into application.css & JS into application.js. You can add more top-level files to compile with the precompile directive in config/environments/production.rb (and other envs if you wish.) For example:
config.assets.precompile += %w( public.css public.js )
Then the Sprockets //= require ... directives in those top-level files will determine the composition of final compiled file.
You can use these additional top-level files in your layouts to have different CSS & JS for certain views.
It's probably a bit better to include this as an asset path(as per your example solution it would be):
config.assets.paths << Rails.root.join('app', 'assets', 'javascripts', 'pages')
It also allows you to include paths not in the assets directory (for example with including the bootstrap-sass). These paths are then added to your assets folder in your public directory, and pushed to your asset location if using something like asset_sync.
I found this link, and think may be it helpful for you, please see
keithgaputis's answer. Rails config.assets.precompile setting to process all CSS and JS files in app/assets
I think you can do like following.
# In production.rb
config.assets.precompile << Proc.new { |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "excluding asset: " + full_path
false
else
puts "including asset: " + full_path
true
end
else
false
end
}
As of Sprockets 3 you can use a manifest.js file to declare which files or directories are precompiled. See upgrade docs. So in your config you would add:
config.assets.precompile = %w(manifest.js)
Then in app/assets/config/manifest.js you can have
//= link_directory ../pages .js
Use link_tree if you want js files in nested sub-directories to be precompiled too.

Resources