Developing a gem in parallel with another project - ruby

Let's say your working on a product, and you realise that some of the code is general enough to be extracted out to a gem.
So you create a new project, build the gem, publish it to Rubygems, and then reference it in your main project's Gemfile.
Then you discover a small bug with how the gem interacts with your product. Each time your make a fix, building and installing the gem locally can take about 15 seconds. How do you minimise this to have a quick develop/test cycle?
(Also it seems that the locally built gem's version number could contradict with what you've pushed to Rubygems, leading to confusion.)
Any best practice guides on this subject?

bundler doesn't just know how to get gems from rubygems. You could point it at a git repository
gem 'mygem', :git => 'git => 'git://github.com/...'
or, much more conveniently in this case
gem 'mygem', :path => '~/work/mygem'
where the path option points to the folder with the gem's source

Related

force ruby gem to use alternative gem source

I have a gem that I one of the owner/authors (hyperloop) that depends on another gem (opal-rails) which depends on another gem (opal-jquery).
All gems depend on the gem opal. The problem is the current released version of opal-query is locked to an older version of the opal gem.
The version of opal-jquery on master is okay. For whatever reason the author(s) have not pushed ruby gems, so I have to work around this.
The work around is that I have to say
gem 'hyperloop'
gem "opal-jquery", git: "https://github.com/opal/opal-jquery.git", branch: "master"
in the application Gemfile.
I am hoping somebody can give a workaround that could be embedded in the hyperloop gemspec, so that the problem is taken care of there.
I thought if I added
gem "opal-jquery", git: "https://github.com/opal/opal-jquery.git", branch: "master"
to the hyperloop Gemfile this would take care of it, but apparently not.
There isn't really a way to manage the dependencies of your dependencies. You have 2 options here:
1) Use an older version of opal
2) Clone the opal-jquery gem and modify its Gemfile, pointing to the version of opal you want it to use, then, in your Gemfile, point the opal-jquery gem to pull from your cloned version of the repo
Neither of these is really ideal and you'd have issues if you ever decided to upgrade to a newer version of opal-jquery if you go with the second route

Installing a modified gem? ( install gem from custom github/branch globally)

I'm new to Ruby and have searched for and tried several Gems that read .doc & .docx files. Yomu
seems the best but it's super slow. This it seems is due to server mode. I've come across a modification for this. I just can't seem to figure out how to install this modified Yomu Gem over the original on my system.
You can set a git and branch in your Gemfile for this gem (see documentation)
# Gemfile
gem 'yomu', :git => 'https://github.com/jeremybmerrill/yomu.git', :branch => 'feature/servermode'

Ruby bundler: use gem from mercurial repository

As everyone know, we can use gem from git repository:
gem 'nokogiri', :git => 'git://github.com/tenderlove/nokogiri.git', :branch => '1.4'
(example from http://bundler.io/gemfile.html)
But I prefer Mercurial, so is it possible to use gem from Mercurial repo?
Currently no, however there has been some activity to add it. The most recent seems to be Bundler Issue #1219.
The work around I would go with would be to either clone locally and use the file path in the Gemfile. Perhaps using Ryan Bigg's nifty Bundler Local Paths Trick on the development system. Unfortunately this is not a good solution for deploying.
Hopefully the bundler team will merge in support at some point.

When developing a gem, do I have to keep installing after I make updates?

I am making a gem in the folder:
/Users/me/projects/ruby/gems/mygamename/
And its layout is like:
/Users/me/projects/ruby/gems/mygamename/mygamename.gemspec
/Users/me/projects/ruby/gems/mygamename/mygemname.rb
/Users/me/projects/ruby/gems/mygamename/lib/mygemname/file1.rb
/Users/me/projects/ruby/gems/mygamename/lib/mygemname/file2.rb
Now in my other ruby project, I want to reference this gem in my Gemfile so I did:
gem 'mygemname', :path => "/Users/me/projects/ruby/gems/mygamename"
I know I should be writing tests for my gem to test for functionaly, but I was curious if I could also do integration tests from my other ruby project (where I am referencing it in my Gemfile).
Do I have to re-run bundle if I make updates to the gem? Or does it keep reading from that folder and it will pickup the changes?
Any other advise on how I can test it from my other ruby project?
Again I will be writing tests in the gem itself, but wondering how I can do I this way also in case I want to.
You will have to run bundle install only once. Bundler does not cache or package your gem, it points to your folder directly.
Restarting rules are the same as in the main app. If you make changes to views, assets or autoloaded ruby files, they will be reloaded automatically. However, you will have to restart your app if you required some lib files in the app and changed them. By default Bundler will require "lib/mygemname.rb" of gem "mygemname", so this file will not be reloadable.
Gem classes/modules are cached so every time you make a change to your gemfile, you will have to restart your app.
Also, if you dont update gem version in your gemspec than you dont have to re-bundle. if you update gem version, than you might need to execute bundle update gemname
What I typically do when developing a gem is create Gemfile in a directory and work from there. In the Gemfile, I add a reference to my gem using the :path option.
gem 'mygemname', :path => '/path/to/my/gem'
Then I run bundle install. This way I don't have to keep reinstalling my gem.
Keep in mind that you need to use bundle exec when running my gem.

unpacking/freezing gems into a non-rails ruby app

I'm writing a non-Rails ruby application (gasp!) and would like to be able to include all the gem dependencies which the application requires in a vendor subdirectory. This would be similar to how http://gemsonrails.rubyforge.org/ works for Rails apps.
The goal here is to avoid the situation my team currently experiences when a new dependency is added. Every developer on my team has to install the gem manually, and then someone has to manually update each test and staging and production machine. If we can freeze the dependencies into the distributed application itself then a simple svn update (or git pull for those hipsters in the crowd) would be all that is needed.
UPDATE (New Solution):
Try Yehuda Katz's new bundler gem. gem install bundler then create a Gemfile with all your dependencies. See the documentation for more info.
Old Recommendation:
One easy way is to just manually unpack the gems into your vendor directory and add the lib path of the unpacked gems to the front of the $LOAD_PATH.
To unpack a gem:
$ cd vendor/gems
$ gem unpack active_support
Unpacked gem: '/path/to/myproject/vendor/gems/activesupport-2.3.2'
Just make sure you unpack all the necessary gems and their dependencies (using the correct versions).
To add all gems under vendor/gems to your $LOAD_PATH, try adding something like this to your application's initialization:
Dir.glob(File.join("vendor", "gems", "*", "lib")).each do |lib|
$LOAD_PATH.unshift(File.expand_path(lib))
end
Update: Sarah (in the comments) convinced me it might also be necessary to override the GEM_PATH. Here's one way to do that:
require 'rubygems'
gem_paths = [File.expand_path(File.join("vendor", "gems")), Gem.default_dir]
Gem.clear_paths
Gem.send :set_paths, gem_paths.join(":")
Another option is to look into Rip (Ruby’s Intelligent Packaging) for managing your dependencies. Rip looks really sweet, but it's still new.

Resources