modifying a gem changes won't take effect - ruby

I am trying to modify the albino gem slightly but any change I make to it does not take effect including ones that should break the gem like dropping everything in the python script https://github.com/austinbv/albino/blob/master/vendor/multipygmentize to one line.
The gem was installed with bundler, and I am using rvm. The gem is stored in ~/.rvm/gems/ruby_version#project I tried editing what I wanted directly, and I tried using
EDITOR=vim bundle open albino and and editing what I wanted. Both of these did not work.
I cannot make any changes to the gem or even break it.
How do you modify a gem so that the changes will take effect.

rails reload only application's classes, not gems dependencies. if you use passenger in development, use "touch tmp/always_restart.txt", else restart application every time you do any changes in gem

The only answer I could find is to uninstall and reinstall the gem I modified it. Not an idea solution but worked for the time being.

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.

Is there a difference between using RVM local gemset and using Bundle exec?

There is fundamental problem with ruby gem sets where commands like rake xxxx might create error because command might use global version of rake while your gemfile requires very specific version.
I know 2 ways to mitigate this.
Use bundle exec in front of rake and rails commands. For example bundle exec rake db:migrate Adding this in front makes sure command is executed in relation of the current bundle meaning the bundle that got created when you run bundle install.
Using RVM. There is less known way of creating local gemset with RVM. First you create directory for your new app in this case mkdir myapp, cd myapp and then run rvm use ruby-2.3.0#myapp --ruby-version --create for creating local gem set with nothing in it. Now you can run gem install rails and rails new . to create rails myapp with it's dedicated gem environment in the folder you are in.
As nice extra RVM will swap to right gemset every time you cd to myapp directory automatically.
As for as I understand both approaches work, but are there any known issues why you would not use one of approaches above?
If you're an RVM fan like myself, I would go with creating my own gemset for every rails project I start. This will make it easier for me to just use rake and rails commands without specifying bundle exec every time.
Put in mind when sharing your code that some developers might be using rbenv or maybe not using a ruby version manager at all. One way you can make sure that everyone is happy and working with the same version of ruby, is to provide two additional files in your project directory (.ruby-version and .ruby-gemset) and track them in your project.
The .ruby-version file would contain the version of ruby you're using for example 2.4.1. Note that this is compatible with both RVM and rbenv and will switch to the correct ruby version.
The .ruby-gemset file is identified only by RVM; thus, switching to the correct gemset you have setup for the project.
This will make your project compatible with developers using rbenv while still making those of us using RVM happy :)
Putting all these considerations in mind, now you should care less wither people use bundle exec or not!
One reason not to use (2): if anyone else wants to work with your code, they will have to duplicate all that for themselves, rather than just remembering to type bundle exec. They have likely never seen (2) before, so this is perhaps non-trivial.

How to install a gem so that it executes independent of currently active RVM gemset?

I am writing a dev command-line tool gem (let's say called "tool") which I would like to use in any place in the system. I use RVM for different projects, but this tool should be available from the command-line inside those projects.
If I simply install the gem globally using "gem install" (let's say it installs to /usr/local/bin/tool), the executable is of course available inside of other projects, but since the gemset changed when executing "tool" it fails saying that it cannot find the "tool" gem (because "tool" was never installed to that gemset). I don't want to add the gem to all the Gemfiles of all the projects.
What's the best way of dealing with this? Perhaps there is a way to "lock" the gem_path/gem_home in the executable at the time of installation?
It turned out that https://github.com/sportngin/brew-gem does what I want, installing a Rubygems gem via brew and locking its GEM_HOME and GEM_PATH in a bin wrapper it generates, so that everything works even when executed in the context of a different RVM gemset.
I forked it into https://github.com/gtmax/brew-gem, adding support for installing a brew gem from a local.gem file or from a gem project on github.

Bundler, when attempting to update or install, will hang forever

When attempting to run bundle install or bundle update, bundler will perpetually hang, and not complete its function. The only time that it will finish is when I specify a gem to update.
For example:
bundle update
Will hang forever unless I use it like this:
bundle update activerecord
Then it will complete as normal.
Any assistance would be appreciated.
This problem is due to a missing dependency, or worse a dependency-of-a-dependency. It's common when you don't use rubygems.org as your gemserver (an enterprise environment).
Common patterns:
You don't have that gem installed
You don't have the dependencies of that gem installed
You don't have that gem installed without its dependencies
Easiest Technique
create a new gemset, and re-bundle. This fixes the problem many times.
If you can't do that for production reasons, and you don't have an app history from which to reflect on when the problem gem was added, then:
Easier Technique
Having learned a bit since writing this answer, I thought I'd pass on this excellent article for how to run bundler with verbose debug output
export DEBUG_RESOLVER=1
bundle 2> debug_output.txt 1> stdio.txt &
This will dump all the debugging (err) output to debug_output.txt and the normal screen stuff to stdio.txt.
You'll want to dump 1> as well because every time bundler dumps a line to 2(stderr) it will put a crlf into 1. So Either dump 1 or background the job. I do both so I can work in the same terminal.
I usually follow it up with:
tail stdio.txt
to be sure things have started, then:
tail -n 10000 -f debug_output.txt
To search with /FAIL] through the file for failed attempts to install a dependency. Find a couple of them that are the same and you've generally located your culprit. The stderr works for bundle install or bundle update.
Debug Your Private Gemserver Technique
I needed to use this process-of-elimination method to determine that my (enterprise) gemserver index had become corrupted
comment out all gems
run bundle update to confirm the empty-set works
un-comment one gem and bundle update
GOTO 3 until you hit the problem
research its dependencies
When you are done
Unset the ENV var with
unset DEBUG_RESOLVER
You can try the --verbose flag too to get more output, but it's really archaic and not very helpful. Really the only way to do this from what I can see is:
Uncomment one gem at a time until it stops working, then try to figure out what the heck is going.
Remove version enforcement one gem at a time (if any) to see if that fixes it.
Remove the offending gem if you can (use a different gem) or lock in versions that do work.
For me, after running:
sudo bundle update --verbose
it kept hanging here:
Query Gemcutter Dependency Endpoint API: tenderlove-frex
Fetching from: http://rubygems.org/api/v1/dependencies?gems=tenderlove-frex
HTTP Success
Query List: []
Not at all helpful. I ended up figuring out that the conflict was between two gems. The following would hang forever:
source 'http://rubygems.org'
gem 'rails', '~> 3'
gem 'airbrake'
I removed the rails version:
source 'http://rubygems.org'
gem 'rails'
gem 'airbrake'
Then it worked, but I noticed in my Gemfile.lock that it was using Rails 2.3.X. So airbrake seemed to be dependent on Rails 2, but I wanted 3. I couldn't find anywhere that airbrake had this Rails 2.x dependency so not sure why it ended up like that. Why bundler can't output something more meaningful is beyond me.
This worked though:
source 'http://rubygems.org'
gem 'rails', '~> 3'
gem 'airbrake', '~> 3'
I really think there is something wrong with Bundler, but not sure.
Bundler may not be hanging. I just experienced a 7 minute time to bundle a relatively small Gemfile, and that is on the fastest possible SSD Macbook Pro with a 50 Gb download connection.
When deploying onto AWS instances, be sure your security group allows outbound HTTP and/or HTTPS connections - I encountered this problem because I had restricted the security group too much.

Why is Phusion Passenger refusing to recognize my updated RubyGems?

I've updated RubyGems everywhere I can possibly think to update it:
The various places I've updated RubyGems http://files.droplr.com/files/14167865/zel8k.Screen%20shot%202010-03-09%20at%2017:24:59.png
but Phusion passenger keeps throwing the same error:
Error Screenshot http://files.droplr.com/files/14167865/zee8W.Screen%20shot%202010-03-09%20at%2017:19:50.png
There is that one freaking place that shows 1.3.1 as the version, despite the file name of 1.3.6. I've obviously borked things up pretty badly here.
That is, I need to update to 1.3.2 or greater and that I currently have 1.3.1.
Any idea how in the world I can get PP to use the correct version of RubyGems and preferably change things so I don't have to face this problem again?
Could this have anything to do with different paths for RubyGems and Ruby environments? These are my environments:
Environment screenshots http://files.droplr.com/files/14167865/zfH6x.Screen%20shot%202010-03-09%20at%2019:07:18.png
First, obtain the value of your PassengerRuby configuration. Then use that Ruby interpreter to run the following script:
http://pastie.org/862871
Like this:
/path-to-your-passenger-ruby-interpreter myscript.rb
and follow the instructions.
That might be of several reasons.
First, verify that you don't have it to explicitly require the rubygem in environment.rb. That is, if you have a line like this:
config.gem "ruby_gems", :version => "1.3.1"
Then you'll have to remove the version from it.
Also, seeing that the rubygems-update gives the incorrect version, you might want to uninstall it.
sudo gem uninstall rubygems-update
Since you have updated it, that gem is not necessary anymore.
I don't think it will help, but I would probably uninstall the macports version of rubygem as well since that might create collisions, even though it doesn't seem like it in this case.
Update:
Since you are using the Ruby from the operating system you don't have to install rubygem through macports at all.
To remove it:
sudo port uninstall rubygems
After that, make sure that you have upgraded the correct rubygem (the binary shows correct, but perhaps there is something missing)
sudo gem update --system
After you've done that. Open up irb (that is, irb and not the rails console) and check the following:
require 'rubygems'
puts Gem::RubyGemsVersion
Also, if you could paste how your apache/nginx configuration looks like, I doubt there is anything wrong in there, but you never know.

Resources