From 8b14275f0f6fcb55271c8b328ee6add7dc29965f Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 14 Apr 2010 19:03:22 +1000 Subject: More expansion on Bundler internals. --- railties/guides/source/initialization.textile | 82 +++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 7df4f8f719..19a4d5157e 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -2114,7 +2114,7 @@ Going back to +Bundler::Dependency+, the next line simply sets +@autorequire+ to @groups = Array(options["group"] || :default).map { |g| g.to_sym } -Here, bundler sets the +groups+ variable to be whatever +group+ we've set for this gem and also demonstrates through code that the +group+ option allows for multiple groups, so in the _Gemfile_ we can specify the same gem for multiple groups: +Here, bundler sets the +groups+ variable to be whatever +group+ we've set for this gem and also demonstrates through code that the +group+ option allows for multiple groups, so in the _Gemfile_ you can specify the same gem for multiple groups: group :test, :cucumber do @@ -2223,7 +2223,7 @@ Now a quick refresher. Bundler is still evaulating the code for the +require+ in end -The second +require+ method here: +The +load+ method returns a +Bundler::Runtime+ object. The second +require+ method here: load(gemfile).require(*groups) @@ -2252,9 +2252,9 @@ Is defined on _bundler/runtime.rb_: end -This method does TODO: Describe what magic this undertakes. +This method does TODO: Describe what magic this undertakes when you've gone through the rest of the source. -The first method to be called here is +autorequires_for_groups+: +The first method to be called here is +autorequires_for_groups+ and this method is defined in _bundler/environment.rb_: def autorequires_for_groups(*groups) @@ -2268,12 +2268,82 @@ The first method to be called here is +autorequires_for_groups+: end -The +specs_for+ method here: +The +specs_for+ method looks like this: - + def specs_for(groups) + deps = dependencies.select { |d| (d.groups & groups).any? } + specs.for(deps) + end + + +The first line here: + + + deps = dependencies.select { |d| (d.groups & groups).any? } + + +Goes through all the +dependencies+ defined and checks to see if their +groups+ match any of the +groups+ defined and returns the ones that are for the groups that are requested. + +The next line firstly calls the +specs+ method: + + + specs.for(deps) + + +Which is defined like this: + + + def specs + @specs ||= resolve_locally || resolve_remotely + end + + +This attempts to resolve the dependencies locally, and if it cannot then it will attempt to resolve them remotely. Firstly, `resolve_locally`: + + + def resolve_locally + resolve(:local_specs, index) + end +The resolve method is defined like this: + + + def resolve(type, index) + source_requirements = {} + actual_dependencies.each do |dep| + next unless dep.source && dep.source.respond_to?(type) + source_requirements[dep.name] = dep.source.send(type) + end + + # Run a resolve against the locally available gems + Resolver.resolve(actual_dependencies, index, source_requirements) + end + + +The +actual_dependencies+ referenced is defined back in _bundler/runtime.rb_: + + + def actual_dependencies + @definition.actual_dependencies + end + + +And the +@definition+ here is a +Bundler::Definition+ object, so that means the +actual_dependencies+ method called here is defined in _bundler/definition.rb_: + + + def actual_dependencies + @actual_dependencies ||= @details["specs"].map do |args| + name, details = args.to_a.flatten + details["source"] = sources[details["source"]] if details.include?("source") + Bundler::Dependency.new(name, details.delete("version"), details) + end + end + + + + h3. Firing it up! -- cgit v1.2.3