Test local version of gem in Rails project - ruby

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).

Related

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.

Customize Gems or merge into main rails project

Currently I am writing a Ruby on Rails application, and I am using Gems, however sometimes I feel that Gems are not as flexible as I want them to be. To make them more flexible. Should I
Fork them on github, and customize it, but this still present the challenging of managing everything.
or
Strip and merge the code of the gem to the main application? This will allow further customization of the gem. This would be for situations where a Gem require another Gem's functionality.
or is there a better way of doing this?
Thanks
B
Choice A is the better answer for a number of reasons.
You get to merge in security updates, enhancements, and bug fixes easily.
Your changes may get merged into the core--in fact, consider if you could implement them in such a way as they live alongside the core functionality as options. If this happens, you have the ultimate win--nothing to maintain, and you can retire your fork.
Others can benefit from your changes.
Your project's footprint is kept smaller and focused by keeping the gem code isolated.
You'll have something to add to your Github "resume."
If its some kind if not so popular gem or "bicycle" from some previous studio or developer who started project(in my case).
I prefer deprecate this gem's and move code into project,
for example they have c***la-deploy - it's just wrapper to Capistrano 2 with own methods))) - I just delete it and rewrite on last Capistrano 3
Than that have own "CMS" c***la-cms where they wrap standard form_for or simple_form with name "twitter_form_for" ? - fist of all I start try to find gem who use this name, and than find in dependency gem's ...
Its take a lot of time for new developer involve in project - better move to standard rails methods/heplers
But anyway i understand for a what this studio do that - its just vendor lock and for client more hard to move out from them to another developers.
For example for startup its bad to use a lot of dependencies and if it's just simple website - dose not matter.

Bundling a forked gem inside a gem

I am trying to build a gem for a project that has a dependency on an unnamed external gem :)
During development I found a small bug in the external project and I added a one line fix that resolves it. I submitted a pull request on github, but I have no response from the maintainer for some time now.
I want to make my project available as a gem but it wont work without this fix. What can I do?
What would be the best way to fix this.
One option I thought about was to create a gem of the forked project and publish it under a convoluted name, and make a dependency on that. But I don't like the idea of polluting the servers with such a stupid gem.
So I was wondering if it is possible to bundle the external gem into my application, and make it install together with my gem. What would be the cleanest and easiest way to do this?
Have you considered overriding the function with your own code? I was having a similar problem with some software at work a few weeks ago and I just redefined the function.
Since it was just one line you found, it seems like this would be the easiest solution, but I am a little bit new to Ruby so maybe there is a problem with this plan that I have not considered.
You could publish it under a different name and once the upstream maintainer accepted your fix, you can yank your version.
It's quite simple, in fact. In your Gemfile add the dependency as:
gem "nokogiri", :git => "git://github.com/tenderlove/nokogiri.git"
To do this you would also need to be using bundler to manage your gem, you can get more info on this here.
The other option is to add the code you changed to a vendor directory in your gem and distribute it with your code, this way you can just add the main directory of this other gem to your load path and you will be able to require it without any issues.
To add something to the load path you simply do:
$LOAD_PATH.unshift( File.join(File.dirname(__FILE__), '..', 'vendor', 'some_gem', 'lib') )
And you will be able to directly require files at some_gem.

Getting newer gems

I'm really just a beginner to ruby, so hopefully this is an easy one. I've got to the point where I'm starting to look into some of the gems that the community have put together. I decided to check out something that would help my application consume rss feeds. So, headed over to rubygems (which is where i thought people go to get these kinds of things) and searched for rss. I found this one;
http://rubygems.org/gems/simple-rss
instructions were to just install the gem with
gem install simple-rss
So far, so good. When i came to actually use the gem, the documentation I received from doing the above was a bit naff, so i searched a bit further and found the git repo;
https://github.com/cardmagic/simple-rss
The documentation there (their code examples) complain about missing methods etc. and after a bit of digging I came to the conclusion that I must have downloaded an older version of the gem than the git trunk.
So, my question is, should I be using rubygems to get the latest gems, and if not, what other resources are out there to help find the latest builds of the comminities gems?
As far as finding a good gem for a task — use Ruby Toolbox, since it also shows you how actively maintained a gem is. Here's, for example, a section on feed parsing.
If you want to get the latest gem code that hasn't been released yet, you could download the code directly from github and build the gem yourself. However, it's easier to use bundler for that. It allows you to create a Gemfile for your project looking something like the following.
gem 'simple_rss', :git => "git://github.com/cardmagic/simple-rss.git"
Then run bundle command to download and build these gems from their corresponding sources.
In general, bundler is a great solution for managing gem dependencies for any ruby project. It provides ways to quickly reference any released gems, automatically builds gems directly from a git source, git refs, or paths on your filesystem, and has other convenient features.
By far the best place for all things Ruby & Ruby on Rails for the devs is the Ruby Toolbox

Resources