Bundling a forked gem inside a gem - ruby

I am trying to build a gem for a project that has a dependency on an unnamed external gem :)
During development I found a small bug in the external project and I added a one line fix that resolves it. I submitted a pull request on github, but I have no response from the maintainer for some time now.
I want to make my project available as a gem but it wont work without this fix. What can I do?
What would be the best way to fix this.
One option I thought about was to create a gem of the forked project and publish it under a convoluted name, and make a dependency on that. But I don't like the idea of polluting the servers with such a stupid gem.
So I was wondering if it is possible to bundle the external gem into my application, and make it install together with my gem. What would be the cleanest and easiest way to do this?

Have you considered overriding the function with your own code? I was having a similar problem with some software at work a few weeks ago and I just redefined the function.
Since it was just one line you found, it seems like this would be the easiest solution, but I am a little bit new to Ruby so maybe there is a problem with this plan that I have not considered.

You could publish it under a different name and once the upstream maintainer accepted your fix, you can yank your version.

It's quite simple, in fact. In your Gemfile add the dependency as:
gem "nokogiri", :git => "git://github.com/tenderlove/nokogiri.git"
To do this you would also need to be using bundler to manage your gem, you can get more info on this here.
The other option is to add the code you changed to a vendor directory in your gem and distribute it with your code, this way you can just add the main directory of this other gem to your load path and you will be able to require it without any issues.
To add something to the load path you simply do:
$LOAD_PATH.unshift( File.join(File.dirname(__FILE__), '..', 'vendor', 'some_gem', 'lib') )
And you will be able to directly require files at some_gem.

Related

Create a completely self-contained gem?

I am writing my first real gem. It depends on three gems, and those gems have roughly a dozen dependencies. I'd like this all to be self-contained so my gem will always use the dependencies from inside the gem, and will not require the other gems to be installed at the system level. Doable?
I played around with bundle install --path vendor --standalone. It did indeed store all the gems' source code into vendor, but I could then not get my 'requires' to work correctly and the code could not be found.
I suspect either that it's not possible to do this with a gem (only and app) or I was missing some piece of configuration to point my gem's code at the vendored dependencies. I played around with $LOADPATH but could not make it work.
Anyone know if this can be done and, if so, how to make it work? Pointers to info welcome.
I think you need to add those gems as a dependency to your .gemspec file. That way when your gem gets installed, its dependencies will also be installed.
More information can be found here

Test local version of gem in Rails project

My Rails site uses a certain gem which is really not very good. Every time I need to do something new I end up having to spend as much time adding features to the gem as I do adding code to the actual Rails project. But I don't mind, and I have my Gemfile set up to point to my GitHub fork of the gem (I tried submitting PRs, but the maintainer seems to have stepped down).
The problem is that I really haven't found a sane way of testing new things I add to the gem. It'd be especially nice to test it within rails c, but the only ways I can think of doing that are a) Changing ~/.rvm/gems/.../foo.rb, which doesn't seem right or b) Bumping the version, pushing to Github, and running bundle up, which in addition to being time-consuming is obviously a disaster since I don't know for sure whether the commits I make are right or not.
I'd even be perfectly happy with a standard irb. But various permutations of require lib/foo from within the gem's directory don't work.
So what's the best practice here?
If you are using a gem and working on it at the same time, the best way is to use Bundler and provide a local path:
gem 'my_bad_gem', path: '../my_bad_gem/'
This will look for the gem under the given (relative in this case) path. Another option is to use local git repositories (see http://bundler.io/v1.3/git.html).

Ruby beginner - using /modifying existing gems in single project

As the title states, I'm a beginner in Ruby.
My project uses 2 existing gems - which I want to modify.
I've forked the gems on GitHub and put them as modules in my repo and they show up as a subdirectory.
I've tried researching this, but I keep on getting lost - I'm thinking I'm missing some basic concepts/knowledge here.
My questions:
Am I going about this right/wrong?
Is it even possible to include the code of those (forked) gems in my actual project, or should I update them separately and just use them as actual gems with require (this seems very cumbersome)
If these gems are part of my project, how do I use them properly, I assume I don't need the require piece? If not, how do I access/use them?
Thanks!
BTW, using Ruby 1.9.2-p194 on Ubuntu with RubyMine as the IDE.
Probably wrong. Ruby is a very flexible language, and has what are called open classes. This means that you can open up and change classes at run-time. Doing this on an external library is called monkey patching. So instead of having to replicate all of the code you want to stay consistent, you can just modify the classes and override any methods you want.
A simple example:
class Fixnum
def is_multiple_of_three?
self % 3 == 0
end
end
However, if the changes you want are really significant, it could make sense to fork the gem.
I recommend the bundler gem. This will let you make a Gemfile which lists all of your dependencies. You can list a github repository as a source for the gem, like so:
gem 'gem_name_here', :git => 'git://github.com/username_here/gem_name_here.git'
and then run bundle install to install your dependencies.
If you install the gems with bundler, it acts just like any other gem you have installed.

Ruby: just-in-time gem installation?

Would it be possible to override the default "require" by adding automatic download-and-install code for any missing includes (provided that the missing include is published as a ruby gem).
Which would not work in situations where Ruby is not interfaced with a shell. But still I think it would be an interesting idea.
Is there such a mechanism in existence today?
Edit:Removed portion about password check. I just checked and gem install doesn't seem to require me to type my password.
You would be able to hijack require method so as gems are installed when an attempt is made to require them, but still you won't have access to newly installed gem in current process, because gem index has to be reloaded.
I understand the intentions but I think exercise might not be worth it.
When installing a fresh gem the gem will be installed in the GEM_HOME. If that is not writable then it will try in the user's home .gem directory (on *NIX at least).
You could certainly script this. In a way Rail's rake gems:build is just this. Just not on demand.
But, I would recommend against this. You could run into build, versioning, dependency and network issues. And probably security issues as well.
PS: Francis Hwang did something related a while ago, although only as a require, not a require gems.
http://fhwang.net/2005/11/01/urirequire-I-got-yer-Web-2-0-right-here
A better option would be to use bundler and distribute the required gems with the application.
It is also quite simple to write a script to bootstrap the installation of gems if you didn't
want to distribute them with your code (using the bundle install/check commands)

What are the steps needed to create and publish a rubygem of your own?

So you've created a ruby library.
How do you create and publish your rubygem? And what common pitfalls and gotchas are there pertaining to creating and publishing rubygems?
There are several tools to help you build your own gems. hoe and newgem are the best-known, and have a lot of good qualities. However, hoe adds itself as a dependency to your gem, and newgem has become a very large tool, one that I find unwieldy when I want to create and deploy a gem quickly.
My favorite tool is Mr Bones by Tim Pease. It’s lightweight, featureful, and does not add dependencies to your project. To create a project with it, you just run bones <my_project_name> on the command line, and a skeleton is built for you, complete with a lib directory for your code, a bin directory for your tools, and a test directory. The configuration is in a Rakefile, and it’s clear and concise. Here's the configuration for a project I did a few months ago:
load 'tasks/setup.rb'
ensure_in_path 'lib'
require 'friend-feed'
task :default => 'test'
PROJ.name = 'friend-feed'
PROJ.authors = 'Clinton R. Nixon'
PROJ.email = 'crnixon#gmail.com'
PROJ.url = 'friend-feed.rubyforge.org'
PROJ.rubyforge_name = 'friend-feed'
PROJ.dependencies = ['json']
PROJ.version = FriendFeed::VERSION
PROJ.exclude = %w(.git pkg)
Mr Bones has the standard set of features you’d expect: you can use it to package up gems and tarfiles of your library, as well as release it on RubyForge and deploy your documentation there. Its killer feature, though, is its ability to freeze its skeleton in your home directory. When you run bones --freeze, a directory named .mrbones is copied into your home directory. You can edit the files in there to make a skeleton for your gems that works the way you work, and from then on, when you run bones to create a new gem, it will use your personal gem skeleton. You can unfreeze Mr Bones by running bones --unfreeze and your skeleton will be backed up, and the default skeleton will be used again.
(Editorial note: I wrote a blog post about this several months ago, and most of this is copied from it.)
I recommend github as a place to start, especially for open source projects.
And try a google search as well... Very first search result for me...
http://www.5dollarwhitebox.org/drupal/creating_a_rubygem_package
You may also want to checkout the Hoe gem, which can automate the gem creation process.
See: http://nubyonrails.com/articles/tutorial-publishing-rubygems-with-hoe
I actually wrote a tutorial on exactly this, and I wrote it as I was learning. It's more focused on the game I'd written than a library. Also, it assumes you want to build the gem via rake rather than on your own:
Part 1 on how to create the gem.
Part 2 on how to run binaries installed by your gem, and get to resources.
hoe no longer adds itself as a dependency as off rubygems 1.2. Its rake tasks are focused on deployment of the rubygem to rubyforge. If you just want to serve the gem from github I think there some new hoe-esque rake task tools to help.

Resources