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

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.

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.

Test local version of gem in Rails project

My Rails site uses a certain gem which is really not very good. Every time I need to do something new I end up having to spend as much time adding features to the gem as I do adding code to the actual Rails project. But I don't mind, and I have my Gemfile set up to point to my GitHub fork of the gem (I tried submitting PRs, but the maintainer seems to have stepped down).
The problem is that I really haven't found a sane way of testing new things I add to the gem. It'd be especially nice to test it within rails c, but the only ways I can think of doing that are a) Changing ~/.rvm/gems/.../foo.rb, which doesn't seem right or b) Bumping the version, pushing to Github, and running bundle up, which in addition to being time-consuming is obviously a disaster since I don't know for sure whether the commits I make are right or not.
I'd even be perfectly happy with a standard irb. But various permutations of require lib/foo from within the gem's directory don't work.
So what's the best practice here?
If you are using a gem and working on it at the same time, the best way is to use Bundler and provide a local path:
gem 'my_bad_gem', path: '../my_bad_gem/'
This will look for the gem under the given (relative in this case) path. Another option is to use local git repositories (see http://bundler.io/v1.3/git.html).

Ruby beginner - using /modifying existing gems in single project

As the title states, I'm a beginner in Ruby.
My project uses 2 existing gems - which I want to modify.
I've forked the gems on GitHub and put them as modules in my repo and they show up as a subdirectory.
I've tried researching this, but I keep on getting lost - I'm thinking I'm missing some basic concepts/knowledge here.
My questions:
Am I going about this right/wrong?
Is it even possible to include the code of those (forked) gems in my actual project, or should I update them separately and just use them as actual gems with require (this seems very cumbersome)
If these gems are part of my project, how do I use them properly, I assume I don't need the require piece? If not, how do I access/use them?
Thanks!
BTW, using Ruby 1.9.2-p194 on Ubuntu with RubyMine as the IDE.
Probably wrong. Ruby is a very flexible language, and has what are called open classes. This means that you can open up and change classes at run-time. Doing this on an external library is called monkey patching. So instead of having to replicate all of the code you want to stay consistent, you can just modify the classes and override any methods you want.
A simple example:
class Fixnum
def is_multiple_of_three?
self % 3 == 0
end
end
However, if the changes you want are really significant, it could make sense to fork the gem.
I recommend the bundler gem. This will let you make a Gemfile which lists all of your dependencies. You can list a github repository as a source for the gem, like so:
gem 'gem_name_here', :git => 'git://github.com/username_here/gem_name_here.git'
and then run bundle install to install your dependencies.
If you install the gems with bundler, it acts just like any other gem you have installed.

How to make a gem available that isn't listed in Gemfile

I made a gem for myself to use in the console. I want to be able to use it all the time everywhere.
I can't figure out how to get Bundler to recognize it without putting it into my Gemfile, but that requires the rest of the people on my team to know about it and have it installed.
Is there a way to get Bundler to overlay a Gemfile of my choosing? Or to somehow generally make my gem available to me even though it is not listed in my Gemfile?
You could circumvent bundler by putting this at the end of the Gemfile and gitignore the Gemfile.dev.rb:
dev_gemfile = File.expand_path("Gemfile.dev.rb", File.dirname(__FILE__))
instance_eval(File.read(dev_gemfile)) if File.exists?(dev_gemfile)
Your Gemfile.lock will not match on different developers' machines if their Gemfile.dev.rb didn't match but I'm only concerned with exact matches in production. Minor changes between developers and production are already an issue if you have multiple platforms and can be worked around in the same way.

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