Bundler: installing a specific .gem file - ruby

Is there a way to tell Bundler to install a particular .gem file I have lying around?
I have a compiled version of ParseTree that I must use (damn you, Windows!), but didn't want to expand the gem file in order to add a :path => '...' attribute to the 'gem' requirement.

You could also package your gems with bundle package, which puts all of your gems in the vendor/cache directory of your project. If needed, overwrite ParseTree with your precompiled gem in in that directory. Then, when you set up your project on another machine, run bundle install --local and it will only install gems that you've packaged.

Instead of setting up your own gem-server, I was able to solve this by writing the following in my Gemfile (the explicit version is crucial):
gem 'libv8', '3.11.8.3mytest', :path => '../libv8/pkg'
And the ../libv8/pkg folder contains only the binary packaged gem libv8-3.11.8.3mytest-x86_64-linux.gem.
Hope this helps.

I don't think you can. As far as I know, you need to gem unpack the .gem into something like vendor/ and set the :path option.

Can't you point the gem declaration to your ParseTree fork at Github?

I figured it out -- thanks to everyone who responded! :)
The trick was to set up a local gem server (with, uh, "gem server") and change my Gemfile's source to point to http://localhost:8808 instead of http://rubygems.org.
This means bundler will grab all the gems from the current installed gem set (which happens to be fine for my case) and then the compiled libs just work.

Related

Can't install gem using Bundler's Rakefile install task when developing a custom gem

I'm developing a couple of private gems and I think I don't understand correctly the PATH/GEM_PATH and/or Bundler/RVM installation flow, would love if someone could chip in.
I have a repository with two gems (A & B for simplicity sake). I've developed the gems using the scaffolding + following the guidelines provided by this bundler tutorial.
Thanks to the Bundler project I have a few Rakefile tasks like rake build, rake install, rake install:local and rake release. Because of the private nature of these gems I can't release them to RubyGems (and we haven't looked into hosting our rubygems).
My machines are using RVM to manage ruby versions and Bundler version 1.15.1
What I want to do: Assuming a new machine/developer trying out the project, ideally we would cd into each of the subfolders (currently 2, gem A and gem B), run rake install and after that we should have the gems available system wide for the current user.
What is happening: The gems are built and work properly, but they are only available inside the subfolder of each gem i.e. gem A is only available inside the subfolder A and gem B is only available inside subfolder B.
What I've tried: So, after rake build/install/install:local a new .gem file is generated under pkg. I've tried to manually install the "compiled" file using gem install pkg/A.gem, gem install --local pkg/A.gem and gem install --local --user-install pkg/A.gem without success. (there are plenty of SO questions/answers about this)
I believe this has something to do with the PATH variables, but like I said before I don't fully understand the way they are managed. I get the following results from these commands:
# Our gem
> gem which A
/home/ubuntu/.rvm/gems/ruby-2.4.0/gems/A-0.1.8/lib/A.rb
# Pry, available globally
> gem which pry
/home/ubuntu/.rvm/gems/ruby-2.4.0/gems/pry-0.11.1/lib/pry.rb
I've been lost and frustrated for far too long now, any help is appreciated. Also open to hear suggestions of better private gem installation flows :)
Yes, it has something to do with your PATH variables. Your installation seems to be good.
I advise you to first affirm your gems installation path with:
echo $GEM_HOME
The double check your PATH to ensure its present and also confirm that the GEM home is also where the gem got installed into from the rake install
echo $PATH
If not, put it in your path and you should be fine with something like this:
echo PATH=$PATH:$GEM_HOME >> ~/.bashrc
source ~/.bashrc
Build your gem as per that guide you linked. You should end up with a gem file. Distribute this as you see fit (I use rsync/crontab to download newer gem versions but anything goes). User can install the gem as follows:
gem install --user-install /path/to/your/file.gem
This will install the gem in the user's ~/.gem/ruby/<version>/gems/<your-gem-name> directory.
Tried it with an empty gem (foodie, as in that example guide) and it works fine. But if you don't specify the --user-install parameter it will try to install in the system ruby dir (/usr/lib/ruby/gems...)

Bundler: using shared gem when it exists, rather than downloading from gem server

Say, I have Gemfile like following.
source "GEM_REPOSITORY"
gem 'gem_A'
# gem_A has no additional dependency
gem 'gem_B'
# gem_B depends on gem_B_1 and gem_B_2
When I run bundle install, I want Bundler to do the following.
If a gem already exists in "local system-wide gems", it copies the gem from local.
If a gem doesn't exist in local, it looks for GEM_REPOSITORY.
I looked for some related articles, and found some of likely-answers like
Ruby Bundler multiple sources in Gemfile
SOURCE PRIORITY
But none of the above looks like the answer for me.
Using source repository priority does't work. Because in the example above, if dependent gem (say, gem_B_1) exits in local but the target gem (gem_B) doesn't exist in local, it'll download both of above from the remote repository.
Are there any work around for doing this?
If not, don't you guys think it's necessary considering the cost of the implementation and the effect?
This is the current behavior.
When running gem install, directly or via bundle install, gem will first build a dependency graph with all the needed gems. If the gem is found locally it will use it, otherwise it will try to download it from the specified source.
If you want, try it yourself.
bundle gem gem_a
bundle gem gem_b
cd gem_a
vim gem_a.gemspec
add
spec.add_dependency 'multi_json', '~> 1.10.1'
or any dependency you want to the gem and run bundle install.
cd ../gem_b
vim Gemfile
and add
gem 'gem_a', path: '../gem_a'
then run
bundle install --verbose
you will see that the multi_json or whatever dependency of gem_a uses the local version and does not download anything.
This is of course also true for gems from remote sources.

Using bundler with "--path vendor", why are gems specified with ":git" not locally vendored?

I'm using bundler and have a Gemfile that looks like this:
source 'http://rubygems.org'
gem 'sinatra', '1.3.1'
gem 'httparty'
# ...etc...
gem 'my_custom_gem', :git => 'git#github.com:me/my_custom_gem.git'
When I run bundle install it fetches the necessary gems, including my custom gem, and installs them in the system gem directory. So far, so good. However, an issue arises when I try to vendor them into a project-local directory. When I run
bundle install --path vendor
It creates the "vendor" directory in my project root and installs all the regular gems there. So I see directories like
vendor/ruby/1.8/gems/sinatra-1.3.1
vendor/ruby/1.8/gems/httparty-0.8.1
...etc...
But it does not vendor the gem specified with a 'git' parameter. I expect to see but do not see anything like
vendor/ruby/1.8/gems/my_custom_gem-1.0.0
It continues to use the system-installed version of this gem. Any explanation for this? Any clean way to get this custom gem vendored as well?
Not supported right now, hopefully coming in Bundler 1.1:
https://github.com/carlhuda/bundler/issues/67
For now you'll have to do:
cd vendor/ruby/1.8/gems/
git clone git://github.com/foo/foo.git
or similar

How to refer a local gem in ruby?

I pack some ruby code into a gem. I want to refer the code in the gem in some other code.
So in the Gemfile I specify the gem's name, version, and local path. Like:
gem 'gemname','0.x', :path => 'RELATIVE_PATH_TO_GEM_FILE'
After bundle install, I see
Using gemname (0.x) from source at RELATIVE_PATH_TO_GEM_FILE
But when I run the code, it can't find the code in the gem. LOAD_PATH shows ABSOLUTE_PATH_TO_GEM_FILE/lib.
No wonder it can't find the code, there's only gem file under ABSOLUTE_PATH_TO_GEM_FILE. it's not unpacked. So there's no lib directory.
if I gem install that gem file into my system, then all works fine. I can see the gem file was unpacked into source code files.
But my question is if it can refer the local gem file directly somehow?
No, you can't refer to a .gem file directly.
In your terminology, you need to use an "unpacked" gem.
:path => '/foo/bar/'
where /foo/bar/ is a (gem) directory with lib/, etc.
We made a local (not system-wide) gems location. We set these environment variables:
GEM_HOME=/path/to/rubygems-1.3.4
RUBYLIB=/path/to/rubygems-1.3.4/lib/
By setting those, we can then do 'gem install ...' to put the built gem into that directory, and ruby knows where to find them.

Manually adding a Ruby Gem

I am trying to install the mechanize gem that is supposed to work with 1.9 from here: http://github.com/kemiller/mechanize but I do not know how to add it manually.
I am using Windows, I could just copy the folder to the gems directory, but how do I initialize it?
I'm not sure I understand the problem. gem install mechanize doesn't work? It produces version 0.9.3 for me, which matches the gemspec of the library you linked to.
EDIT: you're on 1.9. I knew that. Disregard my hasty post, not familiar enough with Windows to offer any help on building the extensions.
I would use the bundler gem using the command gem install bundler. This will create a file called Gemfile in your project directory where you can put your dependencies for the specific project that you are working on. In the Gemfile, you will need to specify gem mechanize. If you want a specific version include ~> VERSION after. After, run the command bundle install. This will install the gem you want and use it in your project.

Resources