Why should I add development dependencies to my gemspec - ruby

It seems like a strange feature that rubygems wants to know what my development dependencies are, so far I never saw it used to actually load these when running the gem tests.

If someone decides to hack your gem for whatever reason, e.g. they fork it on Github to add a feature to it (which they might want to contribute), it helps if they know what development dependencies your gem needs (e.g. testing frameworks, mocking tools etc.).
If you're using bundler with the gemspec command, it will hook into your gemspec dependencies and install the development dependencies along with the runtime ones when you run
bundle install
This saves you having to install these gems manually.
The gem command can also list all the dependencies of a gem including the development ones:
gem dependency my_gem
Gem my_gem-0.1.3
activerecord (~> 3.0.0)
json (~> 1.4.3, development)
rake (>= 0, development)
rspec (~> 2.5.0, development)
ruby-openid (~> 2.1.0)
Once again this is probably more for other people rather than for yourself.

My gems have normally unit-test. This test requires sometimes gems, which are not needed to use the gem. Or perhaps you need additional gems to generate parts of the gem.
Once I misused development dependencies to define 'optional dependecies' (dependecies were necessary for some specific features of my gem, but not needed for the 'normal' usage).
Example:
My application offered the posibility to export to a file as text or pdf. The pdf-generation uses prawn. So prawn is a dependecy - but it is not necessary to use the application, only a specific feature needs it.
So I didn't add prawn to gem dependencies (it is not necessary), but to the development dependencies (it is usefull for the gem).

The documented answer to this question at RubyGems is as follows:
Development dependencies are useful for when someone wants to make
modifications to your gem. When you specify development dependencies,
another developer can run gem install --dev your_gem and RubyGems will
grab both sets of dependencies (runtime and development). Typical
development dependencies include test frameworks and build systems.
For example, I may specify spec.add_development_dependency 'minitest'
Adding the --dev flag to the gem install command would then pull in the minitest gem automatically. This feature saves another developer from manually having to identify and install the gems necessary for development.

Related

Ruby gem - Requires depending on Runtime Options

I'm developing a ruby gem, and my requires are a mess.
The gem is a web Scraper, which depending on the given options, uses different methods to access the web, and thus needs to require different gems. Some users may never need some gems, or any of them.
My question is, what do I put in my .gemspec:
s.add_runtime_dependency #do I require all the gems here?
Where do I actually require the necessary gems in my code, and how do I do testing?
I don't know the conventions on this. Thanks.
*code: https://github.com/ZirconCode/Scrapah
RubyGems provides two main “types” of dependencies: runtime and development.
Runtime dependencies are what your gem needs to work (such as rails needing activesupport).
Development dependencies are useful for when someone wants to make modifications to your gem. When you specify development dependencies, another developer can run gem install --dev your_gem and RubyGems will grab both sets of dependencies (runtime and development). Typical development dependencies include test frameworks and build systems.
So in Gem Specification file you can add those gems that your gems need to work
Gem::Specification.new do |s|
s.name = "gem name"
s.version = "2.0.0"
s.add_runtime_dependency "daemons",
["= 1.1.0"]
s.add_development_dependency "bourne",
[">= 0"]

Find out binary dependencies of gem

I want to build rpm with my Ruby app and its gems. As far as some gems depends on binaries I want to find out them automatically. For example nokogiri gem depends on libxml. Can I fetch all this dependencies for all gems in Gemfile automatically to pack them into rpm?
Now I do it mannualy and this is boring!
No, unfortunately, this is not possible. RubyGems only records Gem dependencies. It obviously cannot record any dependencies it doesn't know about, how would that even work?
There is a requirements attribute in the gemspec, but that is only intended to be human-readable, not machine-readable.

Where do I have to do my Bundler setup?

If I'm developing a gem using Bundler and RSpec for testing. Where do I do my Bundler.setup? Let's assume my gem is called fancy-gem and my directory setup is similar to the following:
Gemfile
Gemfile.lock
lib/
fancy-gem.rb
Rakefile
README
spec/
...
Should I execute Bundler.setup in my 'fancy-gem.rb' or does this cause problems with other gems which might use bundler? I'm thinking, when I'm not doing this, then there is no way to guarantee that the right version of the third party libraries I'm requiring is loaded.
I already asked, if I need to add Bundler itself to the Gemfile. The answer was no, but now I'm not so sure, because if I do execute Bundler.setup somewhere then Bundler actually is a dependency of my Gem and should be installed along with my Gem when it is downloaded from rubygems.org
In my opinion you should neither depend on bundler, nor use it in your gem. The way I'd do it is simply require your gem's dependencies in lib/fancy-gem.rb (almost every gem only has a handful of runtime dependencies, so this should not be too much of a hassle) and I'd call Bundler.setup only in the development files (like spec_helper.rb or Rakefile). This way you don't screw with applications that use your gem and still get all the convenience of automatic dependency management when developing your gem.

Managing conflicting versions of ruby gems

I am building a framework that loads user provided ruby code. It is basically a plugin mechanism. I want the user provide ruby code to be able to require gems of its own. I intend to have the "plugin" package include a vendor directory with the gems.
How can I load gems that are required by the plugin without having them conflict with my framework's gems? For example, if my framework uses treetop version 1.3.0, and a plugin uses treetop 1.4.2 I want each to work with their specified version.
Likewise, is there a way to prevent plugins from conflicting with each other?
I have looked at gem_plugin, _why's sandbox, and some other tools. But I don't see any library that specifically handles this case - I assume its been done before.
I have also looked at the internals of Bundler to see how it manages gem versions. I am prepared to do some pretty complex stuff if need be. But I am still uncertain of how to go about it.
I also have a lot of freedom in how I implement this. So if you think I am barking up the wrong tree, please say so.
Thanks for any advice.
SIDE NOTE: It occurred to me while writing this that I need something similar to the Classloaders in a Java servlet container. A WAR file can include jar files, and the web application's class loader will prefer those over the jars that are on the global classpath. Is there any way in ruby to segment the ruby "classpath" (i.e. load_path, require, etc)?
To be blunt, you can't have two versions of the same gem loaded at the same time.
Bundler does a good (ish) job of looking through all of the required gems and finding a solution to the various overlapping dependencies, but even so it is limited to only loading one version of a gem at a time.
This leads to plugin developers constantly having to update to support any changes that are made in dependent gems in order to avoid just the situation you describe.
(Don't get me started on the screw up that results from the various competing JSON implementations and the pain you have to go through when you have several gem dependencies all requiring different ones.)
Respectfully disagree with the answer above. Here is how I do it:
ruby -S gem list my_gem
`*** LOCAL GEMS ***
my_gem (1.0.1, 1.0.0, 0.0.2)
`
ruby -S gem lock my_gem-1.0.0 > locklist.rb
which generates list of dependencies for a specific version into locklist
require 'rubygems'
gem 'my_gem', '= 1.0.0'
gem 'gem_base', '= 1.0.0'
gem 'rest-client', '= 1.7.2'
gem 'savon', '= 1.1.0'
gem 'addressable', '= 2.3.6'
gem 'mime-types', '= 1.25.1'
gem 'netrc', '= 0.11.0'
now you can do load('locklist.rb') which will load a specific version of a gem along with its dependencies. Look ma, no Bundler.

Questions about building a new gem using Wycats template

I'm writing a new gem I'm basing off of Yehuda's new gem template and I'm slightly confused. Having a Gemfile with dependencies, and also specifying a gemspec with dependencies seems redundant to me. Can someone explain why this is desirable and if it's truly necessary?
Note, this is the first gem I've ever written so I'm new to all of this.
The .gemspec dependencies tell rubygems what it needs to grab to resolve the dependencies when a user installs your gem. The Gemfile is to manage the dependencies while you develop the gem. Rubygems and Bundler aren't connected, at least not yet.
The gemspec is required to build the gem. The Gemfile is more of a convenience, so that people who are working on your gem can easily pull in all the dependencies via Bundler. In the case that you're developing multiple related gems at once, you may also want to put git sources in the Gemfile, so all of the HEAD versions can be tested against.

Resources