How to replace a Ruby gem with code from a local source directory - ruby

I've been using a Ruby package which I installed as a gem. Now I'd like to modify the code, to try my hand at fixing bugs/adding features. I can download the source for the package from GitHub, however, I'm not sure what to do next.
Is there an easy way I can replace a particular gem with code from a local source directory? Ideally, the process would be simple enough that I'd be able to continuously update as I modify the code.
Also, this package is used as a dependency for other gems, and ideally the other packages which use this gem would then use the updated version. (As the program I'm ultimately running is from one of those other gems.) Is there a way to do the install without also installing those other packages from source?
(This would be on Linux, if it makes things easier.)

Assuming your using bundler you can set this in your Gemfile. If your not sure your using bundler look in the root of your project. There should be one file called Gemfile with no extension. The presence of this file will generally indicate that the project's author is using bundler. All changes described below should be made inside that file.
The :path and :git keys in the gem hashmap can be used to point rubygems to different locations. When I am using :path I will have two different ruby projects. The first project is the active project. The project that I am currently working on. This project requires the gem in question that I need to update. The second project will the the checked out source code of the gem I wish to change. With these two projects setup I can edit the Gemfile of the first project and point it at the second project. This is done using :path.
# The Gemfile of the first project
gem 'the_gem_in_question', :path => '/the/path/to/the/second/project'

There are two ways to modify these files and have the changes show up.
One is using the Gemfile to define a path. For example if you wanted the redis gem locally, you can git clone git#github.com:redis/redis-rb.git then as Stewart pointed above, put it into your Gemfile this line gem 'redis', :path => './pathtoredis/redis' instead of gem 'redis'
Another way, which is a little quicker but harder to track changes and stuff is to just gem open redis to open it in a text editor.

Related

Using Gemfiles with Budler with two projects

TL;TR
We have two projects (minitest project, and a page objects project). The Minitest project uses the page object project. When Jenkins runs the tests, we use a remote git path to the page objects project. When we run it locally we change the gem file in the minitest project to use a local path\or local git repo. This results in us needing to continuously change the gem file. We don't wan't to have to do this. How can we set this up so that we don't need to keep changing the gem file?
The long version
I have two Ruby projects, which are tightly coupled. Both projects are used to support testing with Capybara. One project contains Minitest tests. The other project contains page objects. The minitest project uses the page object project. The page object project is published as a gem so that other teams can use it. Quite often we need to edit both projects at once.
I am using Bundler to manage the gems. These projects used to be in two different git repos.
The tests run in Jenkins, and when we work on them we run them locally. When the tests run in Jenkins the minitest project can reference the page objects project either as a published gem or as a remote git repo.
The problem we had with this is that we kept needing to change the gem file of the minitest project. We would change it from pointing to a remote git repo, to a checked out (local) path. Or we would point to a local git repo. In this case we would still need to update the minitest project's gem file with the local branch name. We needed to edit the gem file with either approach, then we had to remember to change this back before checking in and merging.
We then moved both projects into a single repo. Now the gem file in the minitest project only uses the relative path e.g. path => .... This means that we don't need to constantly update the gem file in the minitest project. However, now when we run bundle install or bundle update, only the gem file from the minitest project is used (at least this is what I assume is happening).
How do I use a different gem path\git repo on my dev machine to what is used in Jenkins, without continuously changing the gem file?
I would like to know what approach should I be using in this case? Can avoid making changes to the minitest project's gem file?
Consider using bundler's groups (in Gemfile):
group :project1 do
gem 'rspec'
end
group :project2 do
gem 'minitest'
end
Then specify which group to use in application.rb, for example
Bundler.require(:project1) # or :project2 depending on the project
More info here: http://bundler.io/groups.html

How to develop a Ruby GEM without having to install it first?

I'm developing a GEM that I've forked and I'm trying to modify it slightly for my app.
I'm finding it difficult and time consuming because for every change I make I have to
uninstall
build
re-install
run the app
Is there an easier way of which doesn't require repeating all steps above?
To use it in some app using bundler
If what you mean is for using it in a app to test it / use it, you can just specify a path for your gem or even point to a git repo in the Gemfile http://gembundler.com/gemfile.html
Like
gem "mygem", :path => "~/code/gems/mygem"
To use it as a standalone gem. i.e: like rspec or rake that can run outside of an app.
Just specify the path to your gem binary when running the gem command, like:
$ ~/path_to_my_gem/bin/mygem some args
If you can execute inside your gem directory (i.e: the command does not create files in the current directory, or needs any specific files from the current directory), just do this:
$ ./bin/mygem some args
Note that this last one is just for future reference, I think it's not applicable in the OP context.
use require_relative to include your files:
require_relative 'yourgem/yourclass'
This is the documentation for the function.

Where are "asset group" gems installed?

I have some gems that are only used for the asset pipeline. One example is:
gem 'jquery-datatables-rails', github: 'rweng/jquery-datatables-rails'
Unfortunately, I can not find exactly where this gem is installed. "gem list --local" does not even show it.
I need to fix it, because I am trying to use Bootstrap styling in datatables, which is allowed in the latest version. But the version of datatables included with the gem is old.
Does anybody know where these gems go? I am very, very confused by the asset pipeline.
I such cases, I fork the project on github and make my changes, and adjust my Gemfiles accordingly. This also makes it reuseable in different projects.
The asset pipeline and Bundler grouping has nothing to do with where gems are installed on your system. You can always run bundle open gemname to open the source of a Gem in your $EDITOR and make quick changes (i.e. for debugging). If you want to actually include changes in a release, though, you are going to want to fork the Gem and make your changes there, then specify the git path in your Gemfile.
As a side note, make sure you run bundle install (or really, just bundle) after making changes to your Gemfile to ensure the Gems all get installed.

Pain-free private gems without bundler?

I want to distribute a sysadmin utility inside our company that depends on not-yet-released gems (say, the github master for fog). We have a private GitHub organization account already, and we all have ssh keys for it.
But: While Bundler can install gems with a simple
gem "sysadmin", :git => "git://github.com/ourorg/sysadmin.git"`
there's no way I can find to do that with bare RubyGems. And people are going to want to install other gems on their own machine, so I wouldn't want to force everyone to use Bundler for their home directory.
I can think of a few solutions, none ideal:
Make a "sysadmin" project that has a Gemfile, have everyone clone it, and have them cd into that project dir to run the utility.
Have them manually download and build the gem on their system every time it changes.
Use a third-party gem-hosting repo, and count on security-by-obscurity to prevent outsiders from finding it. Ick.
Set up a secure internal-only server to run gem server or the like. We currently don't have one (everything's in the cloud), and I'd like to avoid setting one up just for this.
There must be a better way.. what is it? Is there a way to set up an old-style gem source in a github repository?
Use a third-party gem-hosting repo, and count on security-by-obscurity to prevent outsiders > from finding it. Ick.
I wanted to suggest Gemfury, but it sounds like you're not interested in 3rd-party gem-hosting solutions. Can you tell me more about your security concerns?
Disclaimer: I work on Gemfury
there's no way I can find to do that with bare RubyGems
This is covered in the documentation. Use the :path option in your Gemfile:
gem "nokogiri", :path => "~/sw/gems/nokogiri"
And there's no reason this would interfere with their home directory or their own gems. They're not all going to want to put your utilities in their home directory anyway. Let them put the files in whatever directory they want, then either tell them to add it to their $PATH or write a Rake task that automatically creates symlinks in e.g. /usr/bin for them.

How to develop a gem in staging environment?

I am trying to hack through a forked gem (buildr). As such I cloned it from github and began to butcher the code. The official gem is installed on my system (under /usr/lib/ruby.../gems/buildr...). There is an executable which I need to use in my dev process - buildr.
Now I want the buildr executable and the library to point to my forked repo and not the default gem installation. This would be for this gem only. As such, the changes I make against the forked repo is usable directly for testing and so forth.
I would guess I need to load my library prior to the system gem loading. Can somebody recommend the best way to do so?
I did something similar for work when the Spreadsheet gem broke backward compatibility. I put the previous versions code in it's own module and just renamed the gem my-spreadsheet and installed that (I really wanted some of the features of the new gem but I also didn't want to rewrite all my previous code at that point).
If it's just a binary you want to override you could always do some PATH magic, setting the directory of your binary first and thus make sure you always override. But personally I'd prefer making my own copy with a new name and installing that.
you could bump the version in the gemspec for your fork. Then when you install your version of the gem, it will use your (newer) version by default.
change buildr.gemspec
#...
spec.version = '1.3.4.dev'
#...
Then
$ gem build buildr.gemspec
$ sudo gem install buildr-1.3.4.dev.gem
and it should work.

Resources