Why is it "wrong to require rubygems"? - ruby

According to this post, requiring rubygems is an antipattern.
require 'rubygems'
The argument seems to boil down to this:
When I use your library, deploy your
app, or run your tests I may not want
to use rubygems. When you require
'rubygems' in your code, you remove my
ability to make that decision. I
cannot unrequire rubygems, but you can
not require it in the first place.
But couldn't the same argument be made about any Ruby library that you 'require' when you create and share a library of code with other people?

If you look at the comments, you will see the author say this
The point I was not trying to make is
that rubygems is bad or that people
shouldn’t use it. I use rubygems and
think it’s a critical piece of Ruby’s
success – I just don’t have the line
“require 'rubygems'” anywhere in my
library’s source code because it’s not
necessary or convenient and makes it
hard / impossible for other
environments (like bundler, rip, GAE,
debian, hand rolled, etc) to use the
library without rubygems, which is
often important.
I actually didn't really agree with him before I read it, now I do

The main problem with requiring rubygems is that it will cause an error on systems that do not have rubygems installed even if they do have the library that you actually want to require.
Some people work around that by rescuing LoadError when requiring rubygems, but that's kind of ugly.

Rubygems isn't essential to the application, it's just a convenient way of supplying a library. By contrast, the other libraries used are essential to the application.

Related

What are the practical advantages of using `add_development_dependency` in .gemspec?

..vs just listing gems used for the gem development in Gemfile (while everyone uses bundler anyway)..
..except for giving your fingers extra work?
It's not clear there is any.
In theory, RubyGems has the information necessary to run tests with add_development_dependency and test_files (see this question).
Some believe that this should be outside the scope of RubyGems (see this huge thread).
In practice, there is currently no real advantage, and the fact that RubyGems still installs test files by default is a drawback, as might be the lack of flexibility that Gemfile offers.
One benefit of add_development_dependency is that if you publish your Gem to rubygems.org, those dependencies can be listed on the gem's details page. Thus if anyone finds your gem via rubygems.org, they have an idea right away what will be required if they want to contribute to the gem.

Can I get rubygems to ignore gem version conflicts?

I have done a bit of digging through the rubygems code and it doesn't look like there is a built-in way to get it to not throw a Gem::ConflictError even if there is one. During development I might be wanting to test something that I know is not going to touch the code from which the conflict is coming or I know that the whatever version of the erstwhile conflicting gem isn't going to cause a problem. I just want to get on with testing what I want to test and I'll worry about version conflicts later.
I know I can hack rubygems to do this. I can think or multiple ways to get it done. I'm just kind of curious if anyone has already done this, how they did it, and maybe if that code has been shared somewhere. I'm also a bit curious as to why this isn't built in to rubygems as a development tool.
You need to worry about version conflicts now before you can get anything done. As Ruby has a singular root namespace and every dependency gets loaded there it's generally not possible to load multiple versions of the same gem. Other systems like NPM for Node.js are significantly more flexible, it's possible to load any number of versions at the same time, so if you're used to that you'll need to adjust your expectations.
If you're trying to do testing and you want to avoid resolving a conflict, just remove that gem requirement from the Gemfile temporarily.
Ultimately you'll have to fix things, there's no way around it, but you can always be selective about what you require.
If you really know what you are doing, try this:
export NOEXEC_DISABLE=1
ruby you-program.rb
This environment variable will disable search and check for Gemfiles and gem versions.

Use Pry in gems without modifying the Gemfile or using `require`

I am trying to debug a gem that's used by a Rails app.
I cloned the Gem locally to go prying around (and also allows me to do nice things such as git bisect, etc.)
# Gemfile
gem "active_admin", path: "~/dev-forks/active_admin"
However, I am often stuck with adding Pry to a Gemfile somewhere to be able to use it, or calling require "pry" live in the code even though I don't want it in there. For example, I will sometimes forget about it, fix the bug, and then commit to the project with Pry in the Gemfile.
Should I not do that, a LoadError will arise, cannot load such file -- pry (LoadError).
I have to admin I'm a bit lost between the different contexts (Rails project, Gem, local Ruby) and actual gems (Gemfile, require, installed).
How can I use binding.pry in a Gem within Rails, without intervention of the Gemfiles?
Jon from the past! As you know, I have the answers to (almost) all your problems.
In this case, you're actually describing two problems: (a) you can't require 'pry' when Pry is not in the Gemfile, (b) you can't use Pry if you don't require it.
What Bundler does, as Conrad Irwin writes:
Bundler is an awesome gem that gives you a good degree of confidence that "if it works in development, it works in production". It can do this by being vicious about gem dependencies: if it's not in the Gemfile, it's not getting required. It also ensures that everyone's development environment is identical, no more does "it works on my machine" cut it as an excuse.
There are circumstances when this dogmatic dedication to duty can get in the way. In particular all good developers have set up their development environment very personally. Obviously, it's not important that my local tools work in production, and it's positively bad for productivity if everyone is forced to have an identicial development setup.
So in doing all the good things Bundler does for us Ruby developers, it comes by design with a caveat: "what's outside the bundle/Gemfile (eg system gems) doesn't exist anymore." How it does that is by redefining the require process and changes your PATH so that it only sees what's in the bundle.
That means you can't use Pry at all without polluting the Gemfile, you say, right? Not so fast. Conrad Irwin being the smart little cookie that he is, came up with a solution and made Pry Debundle, a gem that temporarily reverses the patches Bundler made to our require.
So all you have to do is just require 'pry-debundle' then, right? Oh... wait. Yep, Debundle is probably not in the Gemfile.
The monkey fix is to hard copy the source of pry-debundle.rb to ~/debundle.rb, and then load that. (For now, you'll need Pry loaded to run that source file, but you can run only the debundle! method to get there, require Pry, and go prying around. A little monkeypatching is needed, but I'm working on a PR.)
if you want to use and debug a gem in your rails app, then it should be in the development and test group of the Gemfile in your app.
you can use tools like pry-debugger https://github.com/nixme/pry-debugger to set breakpoints in your pry session break SomeClass#run.
i think it's valid to add pry to every project that i fork to fix a bug or contribute stuff. just don't put it in the .gemspec files.
if you are pushing binding.pry changes to your repo, you should add commit hooks like Jim pointed out. i don't think that this is a pry related issue, it's dependent on how much care you take when reviewing your diff before pushing it out.

Easy way to distribute ruby script

I have a bunch of ruby scripts in a folder which is added to $PATH and I think that some of them might be usefult to others. So I want to distribute them and the only 'good' way I know is rubygems (gem containing only binary), it has a very useful advantage of versioning, but also a drawback of initialization time (sometimes it takes some seconds before script starts to run). Are there alternatives?
Gem is good enought for this. I use gem for this purposes as it is very convenient to intall and update.
Gems are built for this. I'm not sure what you think a gem is, but RubyGems is a repository like PEAR for PHP, aptitude for ubuntu, or CPAN for perl, except they contain ruby libraries.
There is no extra overhead or "initialization time" added to your ruby libraries by making them gems. RubyGems simply installs your library - it doesn't do anything else.
Gems are fine for this kind of Ruby script.
To quickly generate a new gem, try out bundle gem.
To quickly distribute gems without using rubygems.org, and in a way that could work for private deployment, check out the idea for microgems.
If you still don't think you need to wrap these in gems, you can simply add the executable bit to your scripts, add shebang lines for ruby, and remove the .rb extension. Then share your script files with whoever wants them.

Ruby: just-in-time gem installation?

Would it be possible to override the default "require" by adding automatic download-and-install code for any missing includes (provided that the missing include is published as a ruby gem).
Which would not work in situations where Ruby is not interfaced with a shell. But still I think it would be an interesting idea.
Is there such a mechanism in existence today?
Edit:Removed portion about password check. I just checked and gem install doesn't seem to require me to type my password.
You would be able to hijack require method so as gems are installed when an attempt is made to require them, but still you won't have access to newly installed gem in current process, because gem index has to be reloaded.
I understand the intentions but I think exercise might not be worth it.
When installing a fresh gem the gem will be installed in the GEM_HOME. If that is not writable then it will try in the user's home .gem directory (on *NIX at least).
You could certainly script this. In a way Rail's rake gems:build is just this. Just not on demand.
But, I would recommend against this. You could run into build, versioning, dependency and network issues. And probably security issues as well.
PS: Francis Hwang did something related a while ago, although only as a require, not a require gems.
http://fhwang.net/2005/11/01/urirequire-I-got-yer-Web-2-0-right-here
A better option would be to use bundler and distribute the required gems with the application.
It is also quite simple to write a script to bootstrap the installation of gems if you didn't
want to distribute them with your code (using the bundle install/check commands)

Resources