Use ruby gem from git repo via Bundler - ruby

I have created a custom gem using bundler and checked it in a git repo.
custom_gem.rb
require "custom_gem/version"
require "custom_gem/custom_class"
module CustomGem
# Your code goes here...
end
custom_class.rb
require 'typhoeus'
module CustomGem
class CustomClass
def self.custom_method
#do stuff with typhoeus
end
end
end
Added it as a dependency to another project and installed it via bundler.
gem 'custom_gem', :git => 'git#bitbucket.org:dir/repo.git'
After that I try to use it by calling
CustomGem::CustomClass.custom_method
and I get the following error:
uninitialized constant CustomGem::CustomClass
Any suggestions?
Might be a small thing but just starting out with ruby so any advice would be great.

Two things to check :
What happens when you run Bundle install (is the gem listed as installed ?)
Did you require the gem properly (require 'custom_gem') ? Rails does a little magic there, but I'm not sure if you are in a rails application.

The file custom_gem.rb should be in lib/custom_gem.rb, and the file custom_class.rb should be in lib/custom_gem/custom_class.rb
lib/custom_gem/custom_class.rb
\_/ \________________________/
| |
| \_ comes from your code: `require "custom_gem/custom_class"`
|
|
\_ comes from custom_gem.gempsec (the line `s.require_paths = ["lib"]`)
For more about the load path, file hierarchy and naming, check out this gem guide.

Related

Why does jruby-openssl gem have strange folder structure?

From my understanding, a gem's folder structer is supposed to have a folder called lib and inside that folder have a <gem-name>.rb file. However, when I used jruby 1.6.8 and do bundle install to install jruby-openssl, I open up C:\jruby-1.6.8\lib\ruby\gems\1.8\gems\jruby-openssl-0.8.2 and instead of seeing an rb file, I see more sub folders that look like this:
jruby-openssl-0.8.2\
+---lib\
| +---1.8\
| | +---openssl\
| | +---openssl.rb
| +---1.9\
| | +---openssl\
| | +---openssl.rb
| +---ruby\
| | +---shared\
| +---shared\
| +---jopenssl\
| +---openssl\
| +---openssl.rb
+---test\
+---java\
Is there a reason that jruby-openssl isn't following the standard gem folder structure? Specifically, I seem to be having trouble with a gem 'jruby-openssl' command working. Should the gem command find and load the gem correctly if the jruby-openssl folder is in the LOAD_PATH?
ERROR DETAILS:
Here is the error that appears in C:\apachetomcat632\logs\MyWebapp.log
--- Backtrace
LoadError: OpenSSL::Cipher requires the jruby-openssl gem
(root) at file:/C:/apachetomcat632/shared/lib/jruby-complete.jar!/META-INF/jruby.home/lib/ruby/site_ruby/shared/jruby/openssl/autoloads/cipher.rb:8
MessageEncryptor at file:/C:/apachetomcat632/shared/lib/jruby-complete.jar!/META-INF/jruby.home/lib/ruby/site_ruby/shared/jruby/openssl/autoloads/cipher.rb:24
ActiveSupport at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/message_encryptor.rb:12
(root) at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/message_encryptor.rb:4
require at org/jruby/RubyKernel.java:1062
require at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251
load_dependency at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:236
require at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251
eager_autoload! at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/message_encryptor.rb:43
each at org/jruby/RubyArray.java:1620
eager_autoload! at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/activesupport-3.2.11/lib/active_support/dependencies/autoload.rb:43
Bootstrap at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/application/bootstrap.rb:20
instance_exec at org/jruby/RubyKernel.java:2091
run at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/initializable.rb:30
run_initializers at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/initializable.rb:55
each at org/jruby/RubyArray.java:1620
run_initializers at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/initializable.rb:54
initialize! at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/application.rb:136
send at org/jruby/RubyKernel.java:2105
method_missing at file:C:/apachetomcat632/shared/lib/cfe-gems.jar!/gems/railties-3.2.11/lib/rails/railtie/configurable.rb:30
(root) at C:/apachetomcat632/webapps/Bank62P/WEB-INF/rails/config/environment.rb:5
require at org/jruby/RubyKernel.java:1062
load_environment at C:/apachetomcat632/webapps/Bank62P/WEB-INF/rails/config/environment.rb:23
load_environment at file:/C:/apachetomcat632/shared/lib/jruby-rack.jar!/jruby/rack/rails_booter.rb:65
(root) at <script>:1
And here is entire cipher.rb file:
require 'rubygems'
# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present
begin
gem 'jruby-openssl'
require 'openssl.rb'
rescue Gem::LoadError => e
raise LoadError.new("OpenSSL::Cipher requires the jruby-openssl gem")
end
To add to tadman's answer, if you look in the gemspec (gems/1.8/specifications/jruby-openssl-0.8.2.gemspec), you'll see this line:
s.require_paths = ["lib/shared"]
When you require 'openssl' in your code, it'll load the one in the shared dir. I believe that file will determine whether to load the 1.8 or 1.9 version.
With that said...
When I try to require 'openssl' with 0.8.2, I get an error:
LoadError: no such file to load -- openssl/dummy
When I use the latest (0.8.8) it works fine. Try upgrading.
Prior to version 1.7.0 of JRuby, 1.9 support was so incomplete that you'd be better off using 1.8 code. This is probably why there needs to be two separate implementations of that particular library.
Bundling them together like this is a little unusual, often 1.8 installations will just lock to an older version of the gem. JRuby presents a challenge here, and this looks like a fairly reasonable solution.

Ruby 1.8.7: Can't load module from custom gem

After creating a custom gem I'd like to reference functions defined in a module it contains.
Custom gem is dsi_core and the module lib/cuke.rb contains simply:
module DsiCore
module Cuke
def self.Features(*args)
puts "Hello world!"
end
end
end
I've installed the gem and can see /var/lib/gems/1.8/gems/dsi_core-0.1.0/lib/cuke.rb exists as it should.
In another gem dsi_fabric there is the code dsi_fabric/lib/dsi_fabric:
require 'dsi_core'
# ...
DsiCore::Cuke.Features(*ARGV)
Trying to run this from the lib/ directory of dsi_fabric gem:
ruby -rubygems ./dsi_fabric.rb arg1 arg2
..results in:
./dsi_fabric.rb:7: uninitialized constant DsiCore::Cuke (NameError)
This refers to the Cuke.Features line in dsi_fabric.rb.
What am I doing wrong?
You're requiring 'dsi_core' instead of 'cuke'. Try changing require 'dsi_core' to require 'cuke'.
If you are testing in existing namespace problem can be namespace, so try with root namespace reference.
::DsiCore::Cuke.Features(*ARGS)
also like I mentioned in comment you need to put
def self.Features(*args)
# ...
end
Hehe I do not like that capital method name annotation but to each his own :)
EDIT
Also try
require 'rubygems'
require 'dsi_core'
I was miscomprehending how Gem imports work.
If you create a gem and add other gem dependencies to it in the gemspec, those dependencies are automagically imported already.
Therefore what I have above is wrong - to import the cuke.rb file from gem dsi_core in gem dsi_fabric you would use:
require 'cuke'
i.e. the require dsi_core is implicit by nature of the Gem specification and gemspec.
Then to reference in the code would be
DsiCore::Cuke
..as I originally posted.
I was confused because mny public gems indicate you should use require with the form:
require `gem-name/module-or-class`.
However this is misleading: the gem name isn't being used at all, but rather a directory named after the gem:
require 'dir-name/module-or-class'
In this example the gem gem-name has the following directory structure:
lib/gem-name/module-or-class.rb
i.e. they've made a folder in the gem's lib/ directory named after the gem itself.

Ruby's autoload not working in 1.8.7 or Ruby Enterprise?

I've written a gem and within a file I am doing this to autoload my main gem logic:
$:.push File.expand_path('lib', __FILE__)
require "oa-casport/version"
require 'omniauth/core'
module OmniAuth
module Strategies
autoload :Casport, 'omniauth/strategies/casport'
end
end
For Ruby versions 1.8.7 and ree, it prints out "no such file to load - omniauth/strategies/casport'
But it doesn't print out this message on version 1.9.2. Is there something off with the location of calling autoload?
The repo for the gem is located at https://github.com/stevenhaddox/oa-casport
EDIT: My gem works for Rails 2 and 3 regardless of version, but doesn't work on Sinatra when using Ruby/REE 1.8.7. Any ideas?
You're adding a wrong path to $LOAD_PATH.
File.expand_path('lib', __FILE__) will evaluate to ${GEM_PATH}/lib/oa-casport.rb/lib which obviously doesn't exist.
Instead, specify your paths in your gemspec:
Gem::Specification.new do |spec|
# ...
spec.require_paths = [ 'lib' ]
# ...
end
PS: Just to solve the initial problem: You probably meant to add the following to $LOAD_PATH: File.expand_path(File.dirname __FILE__).
I checked out the code and it looks like it loads fine with Rails 2 or Rails 3 with Ruby 1.8.7 and 1.9.2, but is only having issues with Sinatra under Ruby 1.8.7 (loads fine with 1.9.2).
I'm still not sure why the discrepancy, but I'll keep looking into it when I get a chance. The fact that it works in most of the environments above seems to tell me the $:.push line isn't really causing any problems (but it may not be necessary since you're using git to package your gem files already in the .gemspec).

How to color unit tests with lib minitest or Test:Unit?

I would like to have unit tests output color in my dev environment. However, I can't make it work on Linux (Debian and Ubuntu). When I include the following libs:
require 'minitest/autorun'
require 'minitest/unit'
require 'minitest/pride'
I get:
/usr/local/rvm/gems/ruby-1.9.2-p136/gems/minitest-2.3.1/lib/minitest/pride.rb:35:in `<top (required)>': undefined method `output' for MiniTest::Unit:Class (NoMethodError)
caused by the code:
MiniTest::Unit.output = PrideIO.new(MiniTest::Unit.output)
I have seen a working Rspec variant. Unfortunately, my Ruby knowledge is not enough to see differences.
Give turn a whirl.
Add this to your Gemfile:
group :test do
gem 'turn', :require => false
end
step 1 : use the latest version of the gem (I think it will be fixed in Ruby 1.9.3)
gem install minitest
step 2 : require "minitest/pride" on the command line, not in your code
ruby -rminitest/pride your_ruby_script.rb
.. and in your code simply require 'minitest/autorun'
require 'minitest/autorun'
If you use Rubymine, just add
-rminitest
in the default configuration of the tests.
=> the configuration would like
-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) -rminitest/pride
simply add these lines to your test_helper.rb file after require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!
in your gemfile add
gem 'minitest-reporters', '~> 1.0.7'
this will get your rake test to be in red and green, but it also brings up the backtrace. to get rid of all those extra backtrace logs add this to your gemfile then bundle:
gem 'mini_backtrace'
then in config/initializers/backtrace_silencers.rb add this line to cut all the extra rvm stuff
Rails.backtrace_cleaner.add_silencer { |line| line =~ /rvm/ }
hope that works for you, let me know if you need more details.
See https://github.com/tenderlove/purdytest/issues/1. It seems to be a known bug with the minitest version shipped with 1.9.2. For the others, adding
gem "minitest"
at the very top of your file did the trick.
I currently use purdytest with 1.9.2
Try look at this post about using turn gem for nice looking and configurable output for minitest.
http://rawonrails.blogspot.com/2012/01/better-minitest-output-with-turn-gem.html
$ gem install mynyml-redgreen --source http://gemcutter.org
# in your test file
require 'redgreen'
redgreen and turn work nicely in conjunction with each other, by the way

How can I write a hook that gets called when a RubyGem is installed?

I'd like to write a Ruby snippet that gets run when my Gem is first installed via [sudo ]gem install mygem. Can it be done?
It doesn't look like it's really supported. I found a "post_install_message" attribute that you should be able to set in the gem spec, but that won't execute code.
You may be able to do it by packaging your on-install code as an extension in your gem (as if it were a native extension), and providing a Rakefile to "build" the extension (i.e. call your code).
I had the same problem. The best solution that I found is as follows:
# your_gem.gemspec
Gem::Specification.new do |spec|
# ...
spec.extensions = ['Rakefile']
end
-
# Rakefile
task :prepare do
# Execute your post-installation code here
end
task default: :prepare
You can try to do this using call of OS commands. I'll quote eample from irb but you can do same in your scripts too.
irb(main):001:0> system 'gem list | grep rails'
rails (2.1.1, 2.1.0)
=> true
irb(main):002:0> system 'gem list | grep railssssss'
=> false
You can use result of this command as the condition of your snippet execution.

Resources