How to find out what groups "gemspec" creates #1607

Closed
lsiden opened this Issue Jan 2, 2012 · 16 comments

Comments

Projects
None yet
4 participants

lsiden commented Jan 2, 2012

Does anybody know how to find out exactly what is the name of the group that "gemspec" in the Gemfile defines? I looked in my Gemfile.lock but don't see anything like ":default" or ":test" or ":development".

You'd think that "bundle list" might have some option to show you which groups your app can require, but no such luck.

Should this be a new feature?

Owner

indirect commented Jan 2, 2012

The gemspec command does not create a group. If you need groups, put them in your Gemfile.

On Jan 2, 2012, at 11:41 AM, Larry Sidenreply@reply.github.com wrote:

Does anybody know how to find out exactly what is the name of the group that "gemspec" in the Gemfile defines? I looked in my Gemfile.lock but don't see anything like ":default" or ":test" or ":development".

You'd think that "bundle list" might have some option to show you which groups your app can require, but no such luck.

Should this be a new feature?


Reply to this email directly or view it on GitHub:
carlhuda#1607

Contributor

lgierth commented Jan 2, 2012

It should actually create a :development group for the gemspec's development dependencies (see https://github.com/carlhuda/bundler/blob/master/lib/bundler/dsl.rb#L37-41).

Edit: It doesn't show up in my lockfile too, however.

Owner

indirect commented Jan 2, 2012

Ah, that is true, and the docs for the gemspec method do say that. :)

Contributor

lgierth commented Jan 2, 2012

WRT to the initial question: all gems with no explicit :group option get the :default group -- this includes the gemspec and its runtime dependencies (see https://github.com/carlhuda/bundler/blob/master/lib/bundler/dsl.rb#L203).

I'm only guessing when it comes to why groups aren't included in the lockfile, but I think the groups simply don't matter that much for resolving dependencies (unless you use the CLI's --with/--without options, of course).

lsiden commented Jan 2, 2012

@lgierth, what I'm really asking is "What group does Gem::Specification.add_runtime_dependency place its argument in?" From the link you gave me, it appears to be :development.

In any case, something is still broken, because Bundler.requre does not 'require' any gems defined in the :default group that "gemspec" in the Gemfile was supposed to create, as mentioned in the original post. Maybe I'll take a stab at looking at it.

Contributor

lgierth commented Jan 2, 2012

#add_runtime_dependency doesn't add the gem to any group, as it's a part of Rubygems and Bundler's gem groups are out of its scope. I also noticed that my above statement about runtime dependencies and the :default group is actually false. The gemspec's runtime dependencies are not directly added to the bundle when calling the #gemspec method. They are added when all the dependencies are eventually being resolved.

The gemspec's development dependencies are handled a little different. The are implicitly added to the bundle when calling #gemspec because the resolver only cares about runtime dependencies and would otherwise ignore development dependencies.

Wrt to Bundler.require: can you expand on this a little? What do your Gemfile, Gemfile.lock and .gemspec look like and how exactly are you calling Bundler.require?

lsiden commented Jan 2, 2012

It's all in https://github.com/lsiden/accounts

#add_runtime_dependency doesn't add the gem to any group, as it's a part of Rubygems and Bundler's gem groups are out of its scope

You are right. My mistake.

The gemspec's development dependencies are handled a little different. The are implicitly added to the bundle when calling #gemspec because the resolver only cares about runtime dependencies and would otherwise ignore development dependencies.

Then Gemfile: gemspec is supposed to throw both the default and dev-only-required gems into the :default group? That's not what I would have expected.

I found this: http://www.automatthew.com/2008/07/developer-dependencies-in-rubygems-120.html, and this: http://numbers.brighterplanet.com/2010/07/28/bundler-to-the-max/. Curiously, neither of these posts mention using both Gemfile: gemspec and Bundler.require(...) to just suck all the gem requirements from the .gemspec file and require them all in one line!

Have I just discovered a new use-case? Doesn't seem likely but you never know. Anyway, to paraphrase author James Dickey: "If that ain't the way it works, it's the way it oughtta." :)

Contributor

lgierth commented Jan 7, 2012

Gemfile: gemspec is supposed to throw both the default and dev-only-required gems into the :default group? That's not what I would have expected.

Nope, gemspec ignores the default (== "runtime") dependencies as only the resolver cares about them. The development dependencies will be added to the :development group.

You can change this group by passing the :development_group option to gemspec.

Curiously, neither of these posts mention using both Gemfile: gemspec and Bundler.require(...) to just suck all the gem requirements from the .gemspec file and require them all in one line!

If you want to use Bundler.require, just pass :default for your runtime code and both :default and :development for your Rake/test code. This makes only sense though, if you're fine with tying your gem/app closely to Bundler. Most of the time bundle's exec command combined with a simple require "foobar" is the more elegant and simple way.

lsiden commented Jan 8, 2012

Thank you Lars. Could you point me to some examples?

Contributor

lgierth commented Jan 8, 2012

Hi, you can just take a look at hatetepe's gemspec and Gemfile. The runtime and test code both don't know anything about Bundler and Rubygems, they only expect all dependencies to be already added to the load path. That's where bundle exec comes into play (for example when invoking hatetepe, rake, rspec, or other scripts). It simply requires bundler/setup which sets up the load path. This way your code can simply require its dependencies without the need to use Bundler.setup/require for setting up the load path.

lsiden commented Jan 8, 2012

Thanks. That's helpful.

Why does hatetepe's Gemfile include gems that aren't in the gemspec? Is that by intent?

Contributor

lgierth commented Jan 8, 2012

I consider development dependencies to be the gems really neccessary for doing development. awesome_print is just my personal choice for simple debugging, so I like it to not be part of hatetepe's "official" development dependencies. yard and rdiscount should actually be defined in the gemspec as they are neccessary for building the API docs, thanks for the hint :)

Rake is in the Gemfile and not in the gemspec because it isn't a real dependency. The specs can be run just with bundle exec rspec spec/ and rake test is just kind of an alias -- I hardly ever invoke it, but it's the standard and people expect it to run the test suite.

lsiden commented Jan 9, 2012

Lot's of info to process. Thanks!

lsiden commented Jan 10, 2012

@lgierth (Lars), after reading your message again, I decided to do a little experimenting. I'm fairly new to Ruby, so I'm trying to learn everything I can:

1.9.2-p290 :058 > s=Bundler.load_gemspec('accounts.gemspec')
 => #<Gem::Specification name=accounts version=0.0.1> 
1.9.2-p290 :059 > s.dependencies.find_all {|d| d.type==:development}
 => [<Gem::Dependency type=:development name="capybara" requirements=">= 0">, <Gem::Dependency type=:development name="cucumber" requirements=">= 0">, <Gem::Dependency type=:development name="rspec" requirements=">= 0">, <Gem::Dependency type=:development name="rdoc" requirements=">= 0">, <Gem::Dependency type=:development name="sinatra-contrib" requirements=">= 0">, <Gem::Dependency type=:development name="mail-store-agent" requirements=">= 0">, <Gem::Dependency type=:development name="mail-single_file_delivery" requirements=">= 0">, <Gem::Dependency type=:development name="haml" requirements=">= 0">] 
1.9.2-p290 :060 > s.dependencies.find_all {|d| d.type==:runtime}
 => [<Gem::Dependency type=:runtime name="rack" requirements="~> 1.3.6">, <Gem::Dependency type=:runtime name="sinatra" requirements=">= 0">, <Gem::Dependency type=:runtime name="thin" requirements=">= 0">, <Gem::Dependency type=:runtime name="data_mapper" requirements=">= 0">, <Gem::Dependency type=:runtime name="dm-types" requirements=">= 0">, <Gem::Dependency type=:runtime name="dm-timestamps" requirements=">= 0">, <Gem::Dependency type=:runtime name="dm-postgres-adapter" requirements=">= 0">, <Gem::Dependency type=:runtime name="mail" requirements=">= 0">, <Gem::Dependency type=:runtime name="logger" requirements=">= 0">] 
1.9.2-p290 :061 > s.groups
 => [] 

I'm still a bit surprised to see Bundler#groups() returns an empty array. I thought it would return [:development, :runtime](in either order).

Of course, I can just do this

1.9.2-p290 :077 > s.dependencies.map { |d| d.type }.uniq
 => [:development, :runtime] 

Thanks for bearing with me. As I said, I'm trying to learn. After all, if I'm going to use a tool, I need to convince myself that I can find out how it works, rather than fall into the habit of cargo-cult-programming.

Contributor

lgierth commented Jan 10, 2012

I tried to verify #groups' behavior like this:

❤ bundle console
1.9.3-p0 :001 > Gem.loaded_specs["hatetepe"]
 => #<Gem::Specification name=hatetepe version=0.4.0> 
1.9.3-p0 :002 > Gem.loaded_specs["hatetepe"].groups
 => []
1.9.3-p0 :003 > Gem.loaded_specs["rspec"].groups
 => []

#groups should IMO really not be empty in both cases. What do you thin, @indirect?

Contributor

xaviershay commented Aug 11, 2013

Not clear to me after all the discussion what is broken or why we care / what this prevents.

Please re-open with a concise summary and a repro on latest bundler.

xaviershay closed this Aug 11, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment