I'm following this gist: https://gist.github.com/riyad/1933884/#file-bootstrap_breadcrumbs_builder-rb-L2
I have the following in my view:
<%= render_breadcrumbs :builder => ::BootstrapBreadcrumbsBuilder, :separator => "»" %>
I put this in my config/application.rb: config.autoload_paths += Dir["#{config.root}/lib/"]
I put the bootstrap_breadcrumbs_builder.rb in my config/lib.
I get this error though: uninitialized constant BootstrapBreadcrumbsBuilder
Since this needs to be auto loaded why not make it an initializer rather than put it in autoload_paths? (i.e. config/initializers/bootstrap_breadcrumbs_builder.rb)
Also if you would like to use autoload_paths it should not be in config/lib but just in lib. config.root will return the base path for the application e.g. /path/to/your/application and lib would be be a sub directory of this.
It is essentially the same as Rails.root so I think this is your issue (you just placed the file in the wrong spot.)
Run a console and type Rails.application.config.root and you will see what I mean.
Related
I see that the following configuration in application.rb:
config.autoload_paths += %W(#{config.root}/app/models/custom_pack/base)
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/custom_container/**/"]
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/helpers/**/"]
config.autoload_paths += Dir["#{config.root}/app/models/custom_pack/extensions/**/"]
is in the autoload_paths:
Rails.application.config.autoload_paths.grep /custom/
=> ["/Users/dviglione/projects/core/app/models/custom_pack/base", "/Users/dviglione/projects/core/app/models/custom_pack/custom_container/", "/Users/dviglione/projects/core/app/models/custom_pack/helpers/", "/Users/dviglione/projects/core/app/models/custom_pack/extensions/"]
But these files are not being loaded. Because I get an error:
`method_missing': undefined method `create_element' for #<MyElement:0x007f82eca39898>
That create_element method is defined in one of the files that should have been loaded.
However, when I use require/require_relative, it does work:
# /initializers/my_initializer.rb
require "custom_pack/base"
# models/custom_pack/base.rb
require_relative 'custom_container/base'
require_relative 'custom_container/parent'
require_relative 'custom_container/child'
Dir[File.join(File.expand_path("../helpers", __FILE__), "*_helper.rb")].each { |file| require file }
Dir[File.join(File.expand_path("../extensions", __FILE__), "*_adapter.rb")].each { |file| require file }
From what I read from the documentation, when you use require 'erb', Ruby looks for the file in the directories listed in $LOAD_PATH. That is, Ruby iterates over all its directories and for each one of them checks whether they have a file called "erb.rb". If it finds any of them, the interpreter loads it and ends the search. Otherwise, it tries again in the next directory of the list. If the list gets exhausted, LoadError is raised. For autoloading, the idea is that when a constant like Post is hit and missing, if there's a post.rb file for example in app/models Rails is going to find it, evaluate it, and have Post defined as a side-effect. Rails has a collection of directories similar to $LOAD_PATH in which to look up post.rb. That collection is called autoload_paths.
So why does require/require_relative work, but autoload_paths does not?
There's a number of things that could be going on here.
1.If a file is following the path: lib/foo/bar.rb the class needs to be defined like:
class Foo::Bar
end
2.Autoload also lazy loads files, which means your models are only loaded when you call them. For example:
puts "I was loaded!"
class MyLibrary
end
irb(main):001:0> require 'mylibrary'
I was loaded!
=> true
irb(main):001:0> autoload :MyLibrary, 'mylibrary'
=> nil
irb(main):002:0> MyLibrary.new
I was loaded!
=> #<MyLibrary:0x0b1jef>
As for the actual usage of autoload, it's recommended to start using require instead. In theory autoload sounds nice but it can cause problems when certain classes are dependent on other modules. Because of this autoload is in the process of being deprecated.
I have a custom class stored in /lib (/lib/buffer_app.rb):
require 'HTTParty'
class BufferApp
include HTTParty
base_uri 'https://api.bufferapp.com/1'
def initialize(token, id)
#token = token
#id = id
end
def create(text)
message_hash = {"text" => text, "profile_ids[]" => #id, "access_token" => #token}
response = BufferApp.post('/updates/create.json', :body => {"text" => text, "profile_ids[]" => #id, "access_token" => #token})
end
end
I'm attempting to use this this class in an Active Admin resource and get the following error when in production (Heroku):
NameError (uninitialized constant Admin::EventsController::BufferApp):
It's worth noting I have this line in my application.rb and that this functionality works locally in development:
config.autoload_paths += %W(#{Rails.root}/lib)
If I try include BufferApp or require 'BufferApp' that line itself causes an error. Am I having a namespace issue? Does this need to be a module? Or is it a simple configuration oversight?
I had exactly the same problem with Rails 5 alpha. To solve it, I had to manually require the file:
require 'buffer_app'
and not: (require 'BufferApp')
Even if Michal Szyndel's answer makes great sense to me, after manually requiring the file, prefixing :: to the constant was non influential in my case.
Anyway I am not satisfied with the manual requiring solution because I need to add code which is environment specific. Why don't I need to require the files manually in development?
Change this
config.autoload_paths += %W(#{Rails.root}/lib)
to this
config.eager_load_paths += %W(#{Rails.root}/lib)
eager_load_paths will get eagerly loaded in production and on-demand in development. Doing it this way, you don't need to require every file explicitly.
See more info on this answer.
Error line says it all, you should reference class as ::BufferApp
I have made a custom link renderer for will_paginate and have placed the code in lib/my_link_renderer.rb
require 'will_paginate/view_helpers/link_renderer'
require 'will_paginate/view_helpers/action_view'
class MyLinkRenderer < WillPaginate::ActionView::LinkRenderer
include ListsHelper
def to_html
html = pagination.map do |item|
item.is_a?(Fixnum) ?
page_number(item) :
send(item)
end.join(#options[:link_separator])
html << #options[:extra_html] if #options[:extra_html]
#options[:container] ? html_container(html) : html
end
end
Then I use it like so:
<%= will_paginate #stuff,
:previous_label=>'<input class="btn" type="button" value="Previous"/>',
:next_label=>'<input class="btn" type="button" value="Next" />',
:extra_html=>a_helper,
:renderer => 'WillPaginate::ActionView::MyLinkRenderer'
%>
It works the first time but the second time I get a uninitialized constant WillPaginate::ActionView::MyLinkRenderer error. I believe I am loading files from lib into my application correctly in my config/application.rb:
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
I get the same problem in the console.
system :001 > WillPaginate::ActionView::MyLinkRenderer
=> MyLinkRenderer
system :002 > WillPaginate::ActionView::MyLinkRenderer
NameError: uninitialized constant WillPaginate::ActionView::MyLinkRenderer
Suspect this has something to do with how rails autoloads things. Should I not be using autoload? Should I be explictly requiring './lib/my_link_renderer'?
I should note this only happens on my production server.
Your MyLinkRenderer class isn't in the WillPaginate::ActionView module, so referring to it as WillPaginate::ActionView::MyLinkRenderer should never work.
You should either refer to it as MyLinkRenderer (without the module name) or define it to be in that module, and move it to lib/will_paginate/action_view/my_link_renderer.rb:
module WillPaginate::ActionView
class MyLinkRenderer < LinkRenderer
…
end
end
The fact that it works first time is a quirk of the way Rails uses const_missing to implement autoloading. If you're curious, see this answer: https://stackoverflow.com/a/10633531/5168
I'm currently migrating an application in rails v2 to v3
In my lib/ i've some modules in subdirectories, for example,
i've the lib/search/host_search.rb
with a
module HostSearch
def do_search(args)
#...
end
end
then I need to use it in a controller named Discovery::HostController < ApplicationController :
def search_results
output = HostSearch.do_search(:search_string => #search_string,
:page => params[:page],
:user => #current_user)
#...
end
But have I get:
uninitialized constant Discovery::HostController::HostSearch
..I tried to put this lines in application.rb but it doesn't work..
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
I found that moving the module to the lib folder or explicitly including the folder to load worked, in your case
config.autoload_paths += %W(#{config.root}/lib/search)
I think there's something syntaxical that we are missing. Another thing is that if you don't want to mess with the application.rb file, require the file, which if I remember, takes the file path from the lib folder eg: search/host_search <- check that.
I think if you put the HostSearch module under a search subdir, (ie in lib/search/host_search.rb), then you need to namespace it:
module Search
module HostSearch
end
end
If you don't want to namespace it, you can should move the file into the lib root: lib/host_search.rb.
See also: https://stackoverflow.com/a/19650564/514483
I have a class ConstData:
class ConstData
US_CITIES = ['miami', 'new york']
EUROPERN_CITIES = ['madrid', 'london']
end
Its stored under /lib/const_data.rb
The idea is that inside a model, controller or view I can do:
ConstData::US_CITIES to get the US_CITIES etc
Rails should load this class automatically, I got this from:
http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/662abfd1df9b2612?hl=en
However this does not work. Can anyone explain me how to accomplish this ?
The post #daniel refers to is from 2008. Rails has changed since then.
In fact, quite recently. Rails3 doesn't load the lib/ directory automatically.
You can reactivate it quite easily though. Open config/application.rb And add, in the config (in the Application class) the followin :
config.autoload_paths += %W(#{config.root}/lib)
Then your lib/ dir will be autoloaded.
The reason autoload_paths didn't work for you and you were forced to do:
Dir["lib/**/*.rb"].each do |path|
require_dependency path
end
is because you forgot to namespace your class.
lib/awesome/stuffs.rb should contain a class/module like this:
class/module Awesome::Stuffs
....
but you had:
class/module Stuffs
....
Rails can only autoload classes and modules whose name matches it's file path and file name.
:)
config.autoload_paths did not work for me. I solved it by putting the following in ApplicationController:
Dir["lib/**/*.rb"].each do |path|
require_dependency path
end
Follow the solution for lib dir be autoloaded:
Remove config.threadsafe! from development.rb and production.rb;
Add in config/application.rb:
config.autoload_paths += %W(#{config.root}/lib)
config.threadsafe!
config.dependency_loading = true