I have the simple following code, which is working in a ruby (not rails) app:
require 'gmail'
Gmail.new('my_account', 'my_password') do |gmail|
end
I am able to get a connection to the Gmail account and do some stuff in there.
However, I want to use this Gem in a Rails app, and therefore I have tried adding the following into the Gemfile:
gem "ruby-gmail", "0.2.1"
gem "mime", "0.1"
However, when I try to use this in a rake task, like this:
task :scrap_receipts_gmail => :environment do
Gmail.new('my_account', 'my_password') do |gmail|
puts gmail.inspect
end
end
I get the following error:
uninitialized constant Object::Gmail
This is solved if I add require 'gmail'. My question is:
Why would I have to require gmail, if I have already specified that in the Gemfile?
The module/class namespace has to match the directory structure. For example, in lib/foo/bar.rb, if and only if the namespace is Foo::Bar can it be auto loaded by Rails, otherwise you have to require it explicitly.
In this case, Gmail is defined as a class, which doesn't match the directory structure. If Gmail was defined as a module (namespace ::Gmail matchs directory structure), then you'll never need to explicitly require "gmail".
Related
I have written a generator which creates the following ruby file and folder:
app/tests/test.rb
in the test.rb file I have a Test class which looks like this:
class Test < MyCustomModule::MyCustomClass::Base
...
end
Now, I want to use its functionality in one of the show.html.erb files creating new instance like this:
Test.new(...).render(...).html_safe
but I am getting the following error:
uninitialized constant MyCustomModule::MyCustomClass::Base
I have use the following answer to link my gem and my rails application. It seems to work as I am able to use the generator, but the gem module and class are not seen in the rails application.
Could anyone tell how to fix this issue?
I have try to follow the tips posted here but still nothing changed:
Adding config.autoload_paths += Dir["#{config.root}/lib/**/"] in application.rb file
I have created my gem structure looking at CarrierWave gem, so the naming should be correct
I try to disable config.threadsafe! but it is already disabled since config.cache_classes and config.eager_load are set to false in development
DEPRECATION WARNING: config.threadsafe! is deprecated. Rails
applications behave by default as thread safe in production as long as
config.cache_classes and config.eager_load are set to true.
Also, looking at adding-asset-to-your-gems rails documentation, it is said that:
A good example of this is the jquery-rails gem which comes with Rails
as the standard JavaScript library gem. This gem contains an engine
class which inherits from Rails::Engine. By doing this, Rails is
informed that the directory for this gem may contain assets and the
app/assets, lib/assets and vendor/assets directories of this engine
are added to the search path of Sprockets.
So, I have done this, and put my model class file in assets folder, but the result is the same.
The following screenshots demonstrate my real case:
The screenshot below displays my gem file structure
Here you can see how I am loading the gem in my Rails application Gemfile:
gem 'thumbnail_hover_effect', '0.0.3', github: 'thumbnail_hover_effec/thumbnail_hover_effec', branch: 'master'
Then I am using the gem generator a ruby file with a cutstom name in app/thumbnails/test.rb folder with the following code:
class Test < ThumbnailHoverEffect::Image::Base
...
end
and trying to use the Test class gives me uninitialized constant ThumbnailHoverEffect::Image::Base error.
Back in the gem files, these are how the thumbnail_hover_effect file looks like
require 'thumbnail_hover_effect/version'
require 'thumbnail_hover_effect/engine'
require 'thumbnail_hover_effect/image'
module ThumbnailHoverEffect
# Your code goes here...
end
and hoe the image file looks like:
module ThumbnailHoverEffect
#
class Image
...
end
end
From what you've posted here there is no ThumbnailHoverEffect::Image::Base defined. Rails autoloading conventions (which you should not be depending on a gem btw, more on that later) would be looking for this file in thumbnail_hover_effect/image/base.rb, but the directory structure you printed does not have that. Of course you could define the class in thumbnail_hover_effect/image.rb and it would work, but the abridged snippet you posted does not show that. So where is ThumbnailHoverEffect::Image::Base defined?
If it's in thumbnail_hover_effect/image/base.rb then that would indicate the file is not being loaded. You can sanity check this by putting a puts 'loading this stupid file' at the top of thumbnail_hover_effect/image/base.rb. That will allow you to bisect the problem by seeing whether there is a problem with your definition of the class, or whether the problem is with loading the proper files. Debugging is all about bisecting the problem.
I need the Ruby module FileUtils to handle some operations with files.
I want to test that this require will work correctly in my controller. So I tried this in my console but got false as a result (this works fine when I'm not in a Rails console but just a plain Ruby console):
Go to the root directory of my project
$ rails c to open my console
> require 'fileutils' returns false.
What is the correct way to require a module via rails console? Why would this return false?
I'm assuming in my controller I can just do something like this, correct?
def create
require 'fileutils'
# my code that uses fileutils.
end
A false response from require means that the module is already loaded. You should be good to go without requiring this in your controller. See docs: http://www.ruby-doc.org/core-2.1.1/Kernel.html#method-i-require
It is most likely already required by default. Just type FileUtils in the console, it should respond
# => FileUtils
Returning false from require means that it's already loaded.
Try this from the console:
FileUtils.pwd
# => "/present/working/directory
The title of this question may need renaming. Any suggestions?
In my Rails application there was an old Module in the /lib folder called foo_blaster.rb. I then installed my gem named foo_blaster.rb. None of the code in the gem executed until I deleted the original FooBlaster module. Why is this? Shouldn't Ruby combine the two Modules?
The Modules are the same
# lib/foo_blaster.rb
module FooBlaster
class Characters
puts "some characters"
end
end
# foo_blaster gem files
module FooBlaster
class Users
end
end
FooBlaster::Characters #=> some characters
FooBlaster::Users #=> NameError: uninitialized constant FooBlaster::Users
What am I missing here?
Rails 2.3.18,
Ruby 1.8.7-p358
If you open up a console (with script/console) and examine the $LOAD_PATH variable, you should see something resembling this:
>> $LOAD_PATH
[
# some entries...
[12] "/your/rails/root/app",
[13] "/your/rails/root/app/controllers",
[14] "/your/rails/root/app/models",
[15] "/your/rails/root/app/helpers",
[16] "/your/rails/root/lib",
# more entries...
[27] "/your/ruby/path/lib/ruby/1.8/gems/foo_blaster-0.0.1/lib"
# rest of entries
]
When you require 'foo_blaster' (which may be done implicitly by Rails, Bundler, or perhaps some other means), Ruby searches the locations in $LOAD_PATH sequentially until it finds the file foo_blaster.rb, loads that file, and stops. In your case, it finds the file in your application's /lib directory. The file from your gem will never be loaded.
If you want to load both files, all you have to do is give them different names and make sure to require them both. For instance, you might rename the file in your application to foo_blaster_extensions.rb, then add an initializer to load it:
# config/initializers/extend_foo_blaster.rb
require 'foo_blaster_extensions'
If there is a case when you need same name file in your core app. You should follow best practices while creating gem i.e., you should namespace your gem. So in that case no conflicts will occur with core application.
I'm really tired of typing my_ar_object.errors.full_messages in my console when i'm testing things...
So, I want to define this:
module ActiveRecord
class Base
def err
errors.full_messages
end
end
end
in my ~/.irbrc so that it is exclusive to script/console.
I don't want to define it in some rails initializer since I don't believe it belongs in the rails project (this is a irb helper)
The problem is, when I do that, this happens:
/.../gems/rails-2.3.5/lib/initializer.rb:437:in `initialize_database':NoMethodError: undefined method `configurations=' for ActiveRecord::Base:Class
Any ideas how I might make this work?
Did you load ActiveRecord in your .irbrc before defining the err method? Try adding
require 'active_record'
or
require 'rubygems'
gem 'activerecord', '2.3.5' # or whatever version you use
before defining the err method.
And another hint: irb looks for an .irbrc file in the current directory and in your home dir. So you could also craft a project-specific .irbrc in your project root directory. This way, you don't have to introduce ActiveRecord to your default irb config since it is a rather hefty dependency.
I have a engine style Rails plugin from which I can create a gem using Jeweler. But when I require it in my Rails environment (or erb) the models within the plugin are not loaded. I have followed a number of tutorials and read just about everything on the subject.
# environment.rb
config.gem 'myengine'
# in irb
require 'myengine'
I have unpacked the gem and verified that all files are present. My init.rb has been moved to a new folder called 'rails' as per. All files in 'lib' are automatically added to the $LOAD_PATH, so require 'myengine' runs lib/myengine.rb. I verified this by putting a puts 'hello' within.
Is it because of the physical presence of plugins in a known place that Rails can add all the models, controller etc. to the relevant load_paths? Do I need to replicate this manually when using a gem?
Would gemspec require_paths be a way of adding additional paths other than lib? I assume however that Rails does not just require every single file, but loads them on demand hence the need for the filename and class name to match?
%w{ models controllers helpers }.each do |dir|
path = File.join(File.dirname(__FILE__), 'app', dir) + '/'
$LOAD_PATH << path
puts 'requiring'
Dir.new(path).entries.each do |file|
if file =~ /\.rb/
puts file
require file
end
end
end
By adding the above to lib/myengine.rb all the models/controllers are required. But like I said in my question this is unlikely to be a good way forward.
Offhand I'd say the part about adding those directories to the search path is right on. What you shouldn't need to do is require each file manually (as you allude to in your last sentence). What Rails does when you reference a non-existent constant is to search for a file with the same name (underscored of course) in the load path.
If for some reason you can not abide by the constraint (think about it long and hard) then you are going to need to dig deeper into Rails and see how the reloading mechanism works so you can tie into it properly in development mode.
The problem was the files (in app) where not being added to the gem because when using Jeweler it only automatically adds files to required_paths which are committed to git.