I had to fork the gem Thor, coz my cli has one command run which is reserved in the Thor lib itself, changed its name to millisami-thor just in the .gemspec as follows:
Gem::Specification.new do |s|
...
s.name = 'millisami-thor'
...
end
and to use it, I pushed the gem under the name millisami-thor to rubygems.org and in the Gemfile of my cli project, I put gem 'millisami-thor', :require => 'thor'
Now while testing bundle exec cucumber features or to try out the executable, just did ./bin/executable --params and it worked out.
Now, I build the gem with gem build gemname.gemspec that generates gemname.gem and installed with gem install gemname.gem and it gets installed as well as the binary too. Fine, till here.
Now, when I use the binary cmd like executable --params, it looks for the original thor library instead of the forked one.
I figured out that this was due to the require ... in the executable.
require 'thor'
require 'fileutils'
require 'gemname/cli'
Cf::CLI.start
coz in there I explicitly required the original thor.
Now, when I change it to require 'millisami-thor, it cannot find and says:
...
custom_require.rb:36:in `require': no such file to load -- millisami-thor (LoadError)
...
In the Gemfile, I could have done gem 'millisami-thor, :require => 'thor' so that it loads the forked gem.
But how can I do the same if its just the require 'millisami-thor' ?
The only option I can think of is to change all the class names to 'MillisamiThor' instead of 'Thor' and the file names too. But this will be too messy and ugly.
I could have spotted this if I had installed my gem and test it before. But I did just in the test environment, in which the bundler requires the millisami-thor's thor file, so I didn't have this problem till today.
Is there any other way out to achieve this without any messy hacks?
You can keep the original gem setup and point Bundler to your git repository fork:
gem 'thor', :git => 'git://github.com/yourname/thor.git', :require => 'thor'
or even a local path
gem 'thor', :path => '/path/to/thor.git', :require => 'thor'
Related
I want to use awesome print without putting it in my rails 5 app. Just in the console. The documentation for requiring it in irb is not working.
That's because bundler isolates the gems available to load to what's in your Gemfile.
The best way to get around this is to add the gem to your Gemfile
gem 'awesome_print', require: false, group: :development
And in your .irbrc, you can require it, so that it is only enabled for you:
begin
require 'awesome_print'
rescue LoadError => err
warn "could not require awesome_print: #{err}"
end
However, if you aren't permitted to add awesome_print to your repository for whatever reason, there are a few hacks to get gems installed, but not in your Gemfile to load in this GitHub Gist.
One such example that could be placed at the top of your .irbrc:
# Add all gems in the global gemset to the $LOAD_PATH so they can be used even
# in places like 'rails console'.
if defined?(::Bundler)
global_gemset = ENV['GEM_PATH'].split(':').grep(/ruby.*#global/).first
$LOAD_PATH.concat(Dir.glob("#{global_gemset}/gems/*/lib")) if
global_gemset
end
cd your/rails/project
irb
inside irb, run:
require 'awesome_print'
require './config/environment'
and you have both rails console and awesome_print gem while the gem is installed outside of the bundler.
I'm creating a Rails web application which uses a shared library of models (as a Rails Engine), stored in a subrepository (Git subtree.) This shared library contains dependencies on other Ruby gems (in my case, HTTParty and Dalli), of which I want to be automatically referenced by the parent project that includes this shared library.
However, my gem's dependencies don't appear to be resolving in the parent project, and when I start my web application, it has missing references to those gem dependencies in the shared library. (i.e. NameError: uninitialized constant ApiClient::HTTParty) If I explicitly add those references to my web app's Gemfile (as in uncomment the Gemfile lines below), everything works fine.
How do I get these dependencies to 'chain', and have the parent project automatically resolve these references?
Here's what my project looks like:
[MyRailsApp]
-- ...
-- [app]
-- [config]
-- [lib]
-- [MyLib]
-- ...
-- [app]
-- [config]
-- [lib]
-- [MyLib]
-- version.rb
-- engine.rb
-- MyLib.gemspec
-- Gemfile
-- Gemfile
MyRailsApp/Gemfile:
source 'https://rubygems.org'
gem 'activesupport', '3.2.13', :require => 'active_support'
gem 'actionpack', '3.2.13', :require => 'action_pack'
gem 'actionmailer', '3.2.13', :require => 'action_mailer'
gem 'railties', '3.2.13', :require => 'rails'
...
# gem 'dalli'
# gem 'httparty'
gem 'MyLib', :path => 'lib/MyLib'
MyLib/MyLib.gemspec:
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "mylib/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "MyLib"
s.version = MyLib::VERSION
s.authors = ["David"]
s.email = ["ops#myemail.com"]
s.homepage = "http://www.mysite.com"
s.summary = "Shared Library"
s.description = "Shared Library"
s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
s.add_dependency "rails", "~> 3.2.13"
s.add_dependency "dalli", ">= 2.6.4"
s.add_dependency "httparty", ">= 0.11.0"
end
Figured it out. I had the wrong line of thinking... I thought Gemspecs, used for installing gem dependencies (which was working just fine), would also be used by Rails to determine what dependencies need to be loaded into memory when the application starts. This is not the case, at least, not when using Rails engines.
For the average gem, it appears that a typical Rails web app has a line in the boot.rb file which loads all gems and dependencies in the application Gemfile. However, this autoloading does not appear to extend to Rails engines listed in the Gemfile. In this case, you must load your dependencies into application memory manually, by finding the engine.rb file (in your Rails engine) and adding require 'yourgem' at the beginning of the file. This will load the dependency when the engine loads.
A friend found and linked me this relevant question/answer, if this explanation isn't sufficient:
https://stackoverflow.com/a/5850503
If you want rubygems to understand your dependencies, package each of them with a proper .gemspec file. You don't have to publish your gem, it can be private and referenced via a git:// type URL.
The thing is, generally your .gemspec needs to be at the root level. You can't bury it in your project as Rubygems does not go out of its way to look for these.
In your use case, MyLib should be a separate thing.
I'm creating a gem (let's call it mygem) that is essentially a Sinatra server intended to be mounted within Rack based apps.
Inside my gem's gemspec file, I have the following:
gem.add_dependency 'kss'
And Inside my gem's Gemfile, I have the following
source 'https://rubygems.org'
gemspec
gem "kss", :path => "/Users/me/code/kss"
Now when running the server from within mygem's folder, this works exactly as expected: instead of fetching out for the kss dependency, it will look on my local drive and load that version.
The problem comes in when I add mygem to a Rails test app Gemfile. In my Rails test app Gemfile, I have the following line:
gem "mygem", :path => "/Users/me/code/mygem"
I would expect, upon a bundle install, that Bundler would load mygem and its dependencies; but for the kss dependency, instead of loading the local dependency, Bundler actually does fetches out to rubygems to find and load it. I'm assuming because in this case, it's only reading from the gemspec line and not including my dependency override.
Is there anything I can do to fix this behavior? I'd very much like to be able to run and test this stuff locally, but Bundler doesn't seem to recognize dependency overrides from a higher level app.
I'm completely open to any suggestions or changes if I'm going about this the wrong way.
Dependencies listed in your gemspec will become dependencies of the implementing application, while dependencies defined in the Gemfile will not become dependencies of the implementing application. I think you should be able to simply adjust the Rails test app Gemfile to be:
gem "kss", :path => "/Users/me/code/kss"
gem "mygem", :path => "/Users/me/code/mygem"
for a Ruby standalone script what Rails like deployment features such as Gemfile / "bundle install" etc
that is assuming you are developing a Ruby script that you want to test and then deployment, and perhaps ship to others, what Rails like deployment approach would you use for say:
a) GEM - marking GEM requirements & having them installed as required - e.g. Rails "Gemfile" where you mark what gems you need and then "bundle install" to install them
b) File Require - automatically loading *.rb files if they are in your script directory (I'm thinking of in Rails where if you put a class file in the apps/model directory Rails automatically load/require's the file for you)
depends on whether it's a tool you expect people to use on every host they find it on or not. also depends on whether the tool can be shared with pubic repos.
if it just has to work, without worrying about whether you've installed the gems via bundler already or not, you can use something like the following from within your standalone script to install gems if not already present (be mindful of system vs. user ruby):
#!/usr/bin/env ruby
require 'rubygems'
def install_gem(name, version=Gem::Requirement.default)
begin
gem name, version
rescue LoadError
print "ruby gem '#{name}' not found, " <<
"would you like to install it (y/N)? : "
answer = gets
if answer[0].downcase.include? "y"
Gem.install name, version
else
exit(1)
end
end
end
# any of the following will work...
install_gem 'activesupport'
install_gem 'activesupport', '= 4.2.5'
install_gem 'activesupport', '~> 4.2.5'
require 'active_support/all'
...
In my humble opinion, a gem is the way to go. Bundler makes it easy to get started; it starts a skeleton for you when you run the command…
bundle gem <GEM_NAME>
Take a look. As long as you specify your dependencies in your gem's .gemspec file, and somebody installs your packaged gem (they won't need bundler, just RubyGems' gem command), the dependencies will be installed as gems along with it.
I just created a new gem (using bundler) and want to add Active Record support. So I added s.add_dependency "activerecord", "~> 3.0" to my gemspec. Then I use Bundler.setup and Bundler.require and thought that I have access to Active Record now, but I haven't. I have to explicitly use require "active_record". Any idea why Bundler.require does not work for me in that case?
Firstly, if you're packaging a gem, do not use Bundler.require. Bundler.require is for apps not gems.
In .gemspec, specify the dependencies of your deployed gem.
In your Gemfile, include the line gemspec to automatically include the dependencies listed in your .gemspec in your Gemfile.
You may also optionally create gem groups for dev and test.
In your code, explicitly require any libraries you need.
I lost a couple of hours on this today so I hope this helps.
(Sources 1, 2)
Secondly, though the ActiveRecord gem is called "activerecord", the lib is called "active_record". This is what you would need in Gemfile.
gem 'activerecord', :require => "active_record"
Unless you include the :require option, ActiveRecord won't be loaded correctly and you won't know about it until you try to use it.
If you want use Bundler you need define your Gemfile with Activerecord
gem 'activerecord', "~> 3.0.0"
Or you need define bundler to use your gemspec with adding gemspec in your Gemfile
gemspec
See http://gembundler.com/rubygems.html
I had this problem, and the issue in my case was that I was naming a directory in my gem active record, as in:
lib ->
active_record ->
base.rb <- containing some monkey patches to base
This was causing mass confusion including sweet error messages like:
Gem Load Error is: uninitialized constant ActiveRecord::Base
Did you mean? ActiveRecord::Base
Simply moving changing the file from lib/active_record/base.rb to lib/active_record_base.rb fixed it for me.