Rails Metaprogramming: where is this gem installed? - ruby-on-rails

Quick metaprogramming question. In my rails 5 project, I'd like to find the installed location of a certain gem in code (ie. not command line).
I started with Bundler.install_path.
Looking under that, I see all the versions of the various gems I have installed for this ruby (I use rbenv, but this should work for rvm too).
/home/user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/mygem-7eafb06c791d/
/home/user/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/mygem-3da2bf38d01a/
...and so on
Is there a way to tell Bundler "Can you tell me the directory where the gem mygem is installed? Or if there was a hash of gem names with their directories (or something like that), that's fine too.
bonus: if there's a guide to the inner workings of bundler, that'd be cool too :)

Bundler has the show command to show the location of a gem:
bundle show mygem

rbenv-bundler is plugin that makes the rbenv shims Bundler-aware so you dont' have to type bundler exec in front of every command.
you can manage setting of the bundler with create a config file inside ~/.bundle/config (mac / linux)
BUNDLE_PATH: ~/vendor/some_path
if you need more information about config the bundler you can check this bundler.io link

Related

How to use rbenv and store gems locally - coming from rvm background

I used to use rvm and I want to start trying out rbenv.
From what I understand, rbenv does not have the same isolation built in when it comes to gems, it is only managing your ruby versions.
I know there is a rbenv addon that handles gems, but I dont' NEED to get it correct?
I can still download gems locally to my project and use bundle exec for each command?
Is there a short cut that I don't have to be so verbose when typing my commands?
Please explain the workflow as I dont' want to assume anything.
Update
I'm confused how to get the gems loaded into a separate folder.
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.

Is there a version manager for Ruby gems?

I'm a new Rails developer. I recently took a class on Rails and now I'm trying to make sure I'm growing in my skill by self-assigning projects that push me. One thing I'm trying to do now is use Radiant CMS to build a blog site. However, I'm running into some problems downloading the Radiant gem. Here's what I did:
When I first tried gem install radiant, it installed most of the required gems but then threw a warning (which I unfortunately did not save verbatim), which was along the lines of:
railties executable will overwrite rails executable. Overwrite? Y/n
Stupidly, I chose "Y". As soon as I did I tested my rails gem by writing rails new testproject and it failed. So I then re-ran gem install rails, told it to overwrite the "railties" executable, then ran gem uninstall radiant to get rid of the core radiant gem (although I do still have railties).
Now, my Rails gem is fixed, and I can create new Rails projects without an issue. However, I reinstalled the Radiant gem, and while it installed, it fails to create a project every time I run it.
I'm pretty sure I broke something, but I'm not terribly concerned about that. What I am concerned about is the fact that it seems that the Radiant gem doesn't really coexist well with the Rails gem, which leads me to my question:
Is there any way to create separate, self-contained ruby gem environments where the current Ruby version will only use the gems in the specified environment?
In essence, I'm looking for what rbenv does, but for collections of gems rather than Ruby versions.
Currently, I have Homebrew installed and I am using rbenv as my version manager. Everything I can find so far talks about managing gems on a project-by-project basis; I'm looking for something that will manage and keep separate the gems that create the projects in the first place. So, for example, environment_a contains rails and httparty while environment_b contains radiant and railties.
I'm not above completely obliterating rbenv and all of my gems and starting from scratch, either, so that's a possibility (and an advantage of being a noob).
You should check bundler, as it does exactly what you need.
Yes: rbenv-gemset
I think that it is better than RVM because it is less invasive.
I have been using rbenv and rbenv-gemset for about 2 years and find it easy to use. It makes it easy to encapsulate the Ruby and gemset in a project, run multiple Rubies and gemsets on one machine, and move a project to another machine.
You can use ruby-build to install other versions of Ruby. There is a trick to installing the latest versions of Ruby.
You may want to have a look at How do I ensure ruby gems are installed in right place to be executed by bundler? It has some relevant (and hopefully useful) info.
Yes, there is.
I think that it's called RVM.
Just like Chris Heald said, You can check more information about it # rvm.io/gemsets/basics
I'd recommend bundler for versioning gems although both RVM and rbenv also have this functionality.
You asked: "Is there any way to create separate, self-contained ruby gem environments where the current Ruby version will only use the gems in the specified environment?"
The best way to do it with rvm is entering your project's directory and then run:
rvm use ruby-x.y.z#your_project_name --ruby-version --create
where x.y.z is your Ruby version for that project, previously installed with rvm install x.y.z
For example, to use the newest Ruby version with a project named acme you would use
rvm install 2.3.1
and then
rvm use ruby-2.3.1#acme --ruby-version --create
This command would create two files in the projects directoty: .ruby-version and .ruby-gemset.
The file .ruby-version would contain just the version number. And the file .ruby-gemset would contain only the name off the gemset, the same name of your project (acme).
It happens that rvm is smart enough to check for these files and use the gemset specified, which will be located at ~/.rvm/gems/ruby-2.3.1#acme and your gems will be located at ~/.rvm/gems/ruby-2.3.1#acme/gems.
Some points:
1) Using your project's name as the gemset name is NOT mandatory. You may use anything you like. It's kind of a standard using project's name, but not mandatory.
2) rbenv probably has a way to do the same, but I don't use rbenv and really don't know how to do that.
Hope this answer helps.

Using RVM Gemsets & Bundler & RubyMine

I use RVM to manage Ruby versions.
In my project I use Bundler to manage gems for the project.
RVM also have gemsets.
Gem in gemset don't have a connection with Bundler's gem. ← Is this correct?
I came to this conclusion because gem files stored in different locations:
RVM gemset: ~/.rvm/gems/ruby-2.0.0-p247#myApp
Bundler: [my_app_dir]/vendor/bundle/gems
So app uses Bundler gems, not RVM gemset gems.
But when I add gem to my Gemfile, RubyMine IDE shows me warning, that this gem is not in RVM gemset. So I add this gem to RVM gemset also (just to get rid of this warning).
So the questions are:
Is there any good reason to add gems in both places (RVM Gemset and Gemfile)?
If no, then why RubyMine warning me about this?
Is there any good reason to add gems in both places (RVM Gemset and Gemfile)?
The gemset is incidental, the Gemfile is absolutely the place to declare your dependencies. Where you store those gems is up to you.
It sounds like Bundler is configured to store them in a project-local path, but you're expecting them to be in a gemset. Bundler got that configuration by running bundle install --path vendor/bundle/gems at some point. It stores that configuration in its project configuration file at project_dir/.bundle/config:
BUNDLE_PATH: vendor/bundle/gems
I'm unfamiliar with Rubymine, but if you run the Rails server using Bundler (i.e. bundle exec rails server) you can ignore that warning. Bundler will correctly load the gems listed in the Gemfile.
If you want to use a gemset instead of the Bundler cache, you can just remove that line from the Bundler configuration file and reinstall your gems with bundle install.
If no, then why RubyMine warning me about this?
My guess is that Rubymine is not reading the Bundler project configuration (in project_path/.bundle/config) and does not understand where the gems are installed.
You (or if you are working in a team, somebody of your team) has once done a bundle install and specified a installation-folder. In your case vendor/bundle/gems. Bundle remembers this setting and all next invocations of the bundle command will use the same path.
There is a good reason to do it that way: your application-folder will contain all requirements and will be easier to redistribute (for instance).
Now if you want that bundle installs your gems in the normal locations, you can do the following:
run bundle install --system which will use the default location
alternatively: bundle stores it settings in a config file, I think .bundle/config and you can
check that one as well. Normally it is not needed, since bundle install --system will set that
correctly again.
then you can safely remove the vendor/bundle/gems folder
No, something's wrong, you shouldn't have anything under vendor/bundle, it should all be under ~/.rvm/gems/ruby-2.0.0-p247#myApp and perhaps ~/.rvm/gems/ruby-2.0.0-p247#global assuming your .rvmrc (or.ruby-version) is setup correctly.
What does "gem env" look like? Also "bundle env"?
So this just took me 3 days, since nothing else I was finding here was helping. I also run multiple projects through RubyMine at the same time (and different versions) so setting my GEM_PATH and launching from command-line doesn't work for me. I use IntelliJ with RM plugin, this should work on RM standalone.
Bundler seems to install custom gems, or gems from custom repos, in a different directory than gems from rubygems, or github.
/Users/YOURUSER/.rvm/environments/ruby-{version}\#yourgemset/bundler/gems
One thing I wasn't able to fix is in the GEMFILE, I have some custom git_sources, and rubymine highlights those and gives me the warning that it cannot find the gem in my bundle (you can ignore this warning; unless the gem doesn't install at all):
gem 'somegem', custom_git:'gituser/repo'
is highlighted and warning is "Gem x cannot be found... in SDK'
However Bundler installed it, and ruby is able to load it.
# TLDR: Steps to have RUBYMine find extra gems, and show up in external libs
vim ~/.rvm/environments/ruby-{your-verion-here}\#{your-gemset}
add the bundler gems path to GEM_PATH entry
export GEM_PATH='/Users/YOURUSER/.rvm/gems/ruby-{version}#yourgemset/bundler/gems:{the rest}'
save the file
Restart RubyMine/IntelliJ, reopen your project (if not open automatically)
Open the Project Structure dialog > Platform SDKs > Choose the GEMSET you're working with
add /Users/YOURUSER/.rvm/environments/ruby-{version}\#yourgemset/bundler/gems to your classpath
Hit OK, then REOPEN the Project Structure Dialog > Project Settings > Project
Your project will likely have no SDK So select the one you're using again and hit OKAY
RM/IJ will now reindex files
You're done, any broken/missing inspection links should now be fixed. And you should be able to introspect into your gems.
In the above instructions that when you run bundle install (from terminal or RM) it works successfully, and that you have RVM correctly setup, and gemset already created
I hope this helps! Let me know if I should clarify anything (happy NYE)

Ruby - how to use bundler on a gemfile to create an environement?

I am joining a Ruby project and I was given a GitHub url for the gemfile. I copied and pasted the gemfile to the root of my ruby setup.
What I wasn't sure about was what the extension of the gemfile should be. Should it be "name.rb" ?
And also what I am confused about is the command I should use. I googled around for the right syntax, but got confused what the syntax should be to use the bundler to create the application from the gemfile that I have.
Advice much appreciated!
The Gemfile should be saved without an extension.
Bundler has many different commands you can use, but it sounds like you are interested in how to get Bundler to install all of the project dependencies. From the Bundler documentation:
bundle install
Install the gems specified by the Gemfile or Gemfile.lock
Since a Gemfile is evaluated as Ruby code it is possible to save it with an extension of .rb. However, Bundler will not automatically find it if you do. If for some reason you do need to save it with a .rb extension this answer shows how it is possible.

What is the need to use RVM .gems file in a Rails application?

There is my question: I wonder why using a RVM .gems (see http://beginrescueend.com/gemsets/initial/ to know what I'm tlaking about) in a Rails app while we use Gemfile to install our gems in our project?
I think that could be useful when deploying a project for the first time and ensure (eg.) bundler is installed before running (automatically?) a command like bundle install through the .rvmrc file.
I am right? Is there any use case I am missing?
In short, I want to know what is the interest of *.gems file?
Thanks in advance for all your help that will make me learn a lot ;)
Using .gems and Gemfile is rather explicit, You need only one of them, .gems file is more useful for small projects or even for your preferred gems, mostly when there is not much dependencies, in contrary Gemfile brings strict dependency management ensuring you will always get proper versions of gems (assuming Gemfile.lock is also used)
There is good support for generating .rvmrc in development version of rvm, it will detect if you have *.gems or Gemfile and include proper code like bundle install in .rvmrc:
rvm get head
cd /path/to/project
rvm --rvmrc --create --install 1.9.3#project
Review the new generated .rvmrc file and remove the parts that are not important for you.

Resources