How to avoid the source being overwritten when compiling a Gem? - ruby

I am trying to install eventmachine Gem, however a line needs to be commented out in the source for this to work on Ruby 2.0 on Windows x64.
I have tried modifying the Gem source in the Ruby build folder but each time I run gem install eventmachine it overwrites my changes. From the command line help there does not appear to be a way to rebuild the gem without unpacking fresh source, however there may be a workaround.
Is there a way to build my slightly tweaked source for this Gem?

Don't install the gem like that. Instead, build your own version and install that instead by specifying the path to the .gem file that is produced as part of the build process.
I've found the easiest way to get this right is to create a fork, set the fork's git path in your Gemfile, and bundle install which will take care of compiling things and installing them correctly.

Ok figured it out thanks to help from #tadman.
Ended up just installing locally from source rather than tweaking the official source downloaded by gem and preventing it from being overwritten. These are the exact steps ...
Clone locally from Github (or wherever)
Make your changes to the source
If there is a .gemspec file in the root directory
Open terminal in the directory and enter gem build GEMNAME.gemspec
Finally enter gem install GEMNAME-VERSION.gem
If there is not .gemspec but there is a file called "gem" or "build" or something similar , then you may have to build using rake according to this reply

Related

Cleaning gems from older gem version

I recently upgraded my distro (Ubuntu from 16.04 to 18.04), and I guess either on the upgrade or on the regular sudo update/upgrade calls gem was upgraded and I currently have the 2.7.6 version. I barely use Ruby lately, but just now I had to run a jekyll/bundle command which returned me that it had a bad interpreter (it was looking for ruby2.3 and it's currently installed on the 2.5 version).
My next step would be updating the jekyll and bundle gems (so they update the interpreter version), but to my surprise they aren't listed when I run gem list. They were obviously installed since there's a /usr/local/bin/jekyll executable and a /usr/local/bin/bundle one as well. But I think when gem was upgraded it started checking gems on a different folder (/var/lib/gems/2.5.0 I'm guessing) but jekyll/bundle apparently are in /var/lib/gems/2.3.0. I'd be fine just installing jekyll/bundle on the 2.5.0 version, but is there a way to remove all gem files from the older version since they are useless now?
I highly recommend you to use a ruby version manager like rvm or rbenv to manage different ruby versions installed on your system.
If you just want to remove the gems from your disk, you can find the location of each gem with the command bundle show $gem_name and delete the parent directory to delete all of them. You may need to delete the Gemfile.lock as well to reset the locked gem versions.
Here's what I recommend:
Use rbenv for multiple Ruby version management, no customizations needed
a ruby installer plugin is now included with rbenv
it also handles ruby executable shims automatically, don't need to rbenv rehash anymore
it loads really fast (rvm has a noticable load time on shell startup)
Use bundler to dynamically resolve gems at runtime (options below)
it's fast enough anyways
don't need a special gem solution, bundler comes included /w Ruby now
Options to invoke bundler dynamically (I recommend the last one):
use bundle exec in front of every ruby executable
variant: create alias be='bundle exec'
create bundle binstubs <LIST GEM EXECUTABLES YOU WANT> for each project
use bin/ in front of every ruby executable to call the binstubs
do #2 and then set up .git/safe
lets you manually allow PATH lookups to the bin/ folder while in that project root
don't need to type bin/ anymore
Now multiple gem versions will all be installed into the same Ruby version bucket, and you let bundler dynamically add the right versions to the load path before every startup.
Removing a Ruby version will also mean removing all the gems (and versions of those gems) installed for that Ruby version as well.
I'd like to thank both answers. I upvoted them because even though they're not a direct solution to my problem they give good directions to prevent it.
NOTE: These are the steps I took, which doesn't mean they are the correct way, so don't take more as a reference than a guide.
Here's what I did to clean up those old Ruby version gems:
First I needed to add an environment variable for gem to be able to find those obsolete gems, by running GEM_PATH=/var/lib/gems/2.3.0.
Then it's possible to get the contents and specification of the gems with gem contents name_of_gem and gem specification name_of_gem.
I individually uninstalled those gems that were obsolete with sudo GEM_PATH=/var/lib/gems/2.3.0 gem uninstall -i /var/lib/gems/2.3.0 name_of_gem. In my case I did a sudo install, so I needed sudo which also required me to set the environment variable again because of sudo's security policy. Also, I needed to manually set the install directory for some reason.
Some gems will have executables, and the uninstall will ask if you want to remove it. I wasn't able to get the gem uninstall to remove it because it claimed I didn't have write permission to /var/lib/gems/2.3.0/bin (which is weird because the EXECUTABLE DIRECTORY gem environment variable was /usr/local/bin). I asked gem not to remove the executables, wrote down their names and removed them manually from the EXECUTABLE DIRECTORY folder. You can also use which gem_executable_name to find out where it's located.
After uninstalling all the gems I believe it's safe to remove the /var/lib/gems/2.3.0 folder and its contents. Running gem contents on all of them only returned me files on this folder so I believe the only external files were the script/executables that were added to /usr/local/bin.

fixing a failed ruby gem install

I am installing the ruby gem mysql-dbd on a new system which is running ruby 2.5. The problem is that it gets a syntax error because at 2.4 ruby combined Integer and Fixed num types.
The failed install leaves the unpacked gem package on disk so I was able to examine the entrails and the fix appears to be trivial (as in insert a '#' in a statement to remove the now redundant reference to FixNum).
My question is having fixed the source how do I go about building and installing the gem? Not being familiar with rake.
BTW the gem has long been "unsupported".
I can't get the gem source repository to load, but you've got at least two options:
Locally, you might be able to build it. Try running rake build from the root folder of the gem, and look in the pkg folder for the built gem. You should be able to then gem install pkg/<gem name>.gem in that folder
If you need to share it with others, push the code up on github. Make your change, and if you're using bundler in the codebase that's using the gem, update your Gemfile to point to your source.
You could try something like this:
# install_dbd_mysql.rb
Fixnum = Integer
require 'rubygems/commands/install_command'
install = Gem::Commands::InstallCommand.new
install.handle_options ['dbd-mysql']
install.execute
Run:
$ ruby install_dbd_mysql.rb

Edit Ruby Gem locally and execute gem?

For a project I'm working on, I have to do some work on an existing Ruby Gem. I haven't got much previous experience with Ruby and am struggling with a few aspects.
I have the repository cloned locally. I need to edit the current files in the /lib/ directory, which I can do. Is it possible for me to compile the edited files into a Gem and run this Gem? Any help would be really appreciated.
Yes! You can include the gem in a local project and point the Gemfile to your local directory:
Gemfile
source 'https://rubygems.org'
gem 'my_local_gem', path: '/absolute/path/to/your/gem'
Then edit the gem, run your local program and see the changes.
Additionally, you don't always have to clone a whole gem, you can install it via rubygems and use bundle open <gem_name> to open the gem's contents in your supplied editor.
I have written a post describing just that and more here.

How to contribute to a Ruby Gem

I am trying to contribute to a Ruby gem and I don't understand how to test a local gem without using a globally installed gem.
The gem I want to contribute to is a command line interface gem. I clone the gem into a directory then cd into that directory. However, when I run commands in the terminal when I'm in the cloned project directory it still uses the global gem. I've even run
gem uninstall gemname
then while inside the newly cloned gem directory I redo
gem install gemname.
No matter what changes I make to the gem, I can't see the results or what my contributions are doing because it's always running the global gem.
When I do try to type a command line command that is supposed to interact with the gem while in the cloned gem directory I get:
-bash: ~/.gem/ruby/2.1.0/bin/githubrepo: No such file or directory
I've done a ton of research but I'm just not getting it. Help?
gem install gemname will look for a .gem file in the current directory. If not found it will look for it on the web.
gem install --local /path/to/your/gemname.gem will allow you to target a particular directory. You may need to gem build gemname.gemspec first, so it has your changes.
Instead of doing this, I would write tests in the gem directory itself. It's likely that when running code in there, you can simply require 'gemname' in Ruby to get the gem functionality.
If it's a well-written gem, it should have tests already. They will most likely be in a directory called test or spec. Have a look at these tests and try to carry on in that style to test your changes. This will make your code changes far far more likely to be accepted as a pull request.

Copy compiled gem to other computer, avoiding compiling again

Using RVM, how can I copy gems between two different computers? The gem is compiled and I want to avoid a compilation on the target machine.
I tried to copy the .rvm/gems/ruby-x.x.x-pxxx#gemset/gems/gem_name directory, and also the /bin and /cache, but in the target computer I can't see the gem in the gem list output.
Is there anything else I need to do?
You have to copy also the gem specification file you find in .rvm/gems/ruby-x.x.x-pxxx#gemset/specifications/gem_name.gemspec.
Keep in mind that the binary code could not run on the destination platform.
You could use gem-compiler from Luis Lavena.
It should be as easy as (replace <gem-*> with actual gem information):
gem install gem-compiler
gem fetch <gem-name> --platform=ruby
gem compile <gem-name>-<gem-version>.gem
This commands will create the *.gem file for your platform which can be then moved to another machine and installed with gem install --local <gem-file>.
For more details check https://github.com/luislavena/gem-compiler#usage

Resources