aboutsummaryrefslogtreecommitdiffstats
path: root/railties/guides
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2010-04-16 15:08:16 -0700
committerXavier Noria <fxn@hashref.com>2010-04-16 15:08:16 -0700
commit09b9add8c5eb85e7369d98a6efa11c5b27787838 (patch)
treef8701879fbf37675467f96a3e47af1173cf8b021 /railties/guides
parent001ca893c6f061796a2c3f03c864fdf06c9efbb1 (diff)
parentf7e9c931412bdee0c6dbce3334fdd66ce226889a (diff)
downloadrails-09b9add8c5eb85e7369d98a6efa11c5b27787838.tar.gz
rails-09b9add8c5eb85e7369d98a6efa11c5b27787838.tar.bz2
rails-09b9add8c5eb85e7369d98a6efa11c5b27787838.zip
Merge commit 'docrails/master'
Diffstat (limited to 'railties/guides')
-rw-r--r--railties/guides/source/action_mailer_basics.textile59
-rw-r--r--railties/guides/source/form_helpers.textile1
-rw-r--r--railties/guides/source/i18n.textile6
-rw-r--r--railties/guides/source/initialization.textile482
4 files changed, 60 insertions, 488 deletions
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index e5ba8380e8..79cb86ee97 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -58,9 +58,9 @@ end
Here is a quick explanation of the items presented in the preceding method. For a full list of all available options, please have a look further down at the Complete List of ActionMailer user-settable attributes section.
* <tt>default Hash</tt> - This is a hash of default values for any email you send, in this case we are setting the <tt>:from</tt> header to a value for all messages in this class, this can be overridden on a per email basis
-* +mail+ - The actual email message, we are passing the <tt>:to</tt> and <tt>:subject</tt> headers in|
+* +mail+ - The actual email message, we are passing the <tt>:to</tt> and <tt>:subject</tt> headers in.
-And instance variables we define in the method become available for use in the view.
+Just like controllers, any instance variables we define in the method become available for use in the views.
h5. Create a Mailer View
@@ -104,9 +104,9 @@ When you call the +mail+ method now, Action Mailer will detect the two templates
h5. Wire It Up So That the System Sends the Email When a User Signs Up
-There are three ways to achieve this. One is to send the email from the controller that sends the email, another is to put it in a +before_create+ callback in the user model, and the last one is to use an observer on the user model. Whether you use the second or third methods is up to you, but staying away from the first is recommended. Not because it's wrong, but because it keeps your controller clean, and keeps all logic related to the user model within the user model. This way, whichever way a user is created (from a web form, or from an API call, for example), we are guaranteed that the email will be sent.
+There are several ways to do this, some people create Rails Observers to fire off emails, others do it inside of the User Model. However, in Rails 3, mailers are really just another way to render a view. Instead of rendering a view and sending out the HTTP protocol, they are just sending it out through the Email protocols instead. Due to this, it makes sense to just have your controller tell the mailer to send an email when a user is successfully created.
-Let's see how we would go about wiring it up using an observer.
+Setting this up is painfully simple.
First off, we need to create a simple +User+ scaffold:
@@ -115,35 +115,38 @@ $ rails generate scaffold user name:string email:string login:string
$ rake db:migrate
</shell>
-Now that we have a user model to play with, edit +config/application.rb+ and register the observer:
+Now that we have a user model to play with, we will just edit the +app/controllers/users_controller.rb+ make it instruct the UserMailer to deliver an email to the newly created user by editing the create action and inserting a call to <tt>UserMailer.welcome_email</tt> right after the user is successfully saved:
<ruby>
-module MailerGuideCode
- class Application < Rails::Application
- # ...
- config.active_record.observers = :user_observer
+class UsersController < ApplicationController
+ # POST /users
+ # POST /users.xml
+ def create
+ @user = User.new(params[:user])
+
+ respond_to do |format|
+ if @user.save
+ # Tell the UserMailer to send a welcome Email after save
+ UserMailer.welcome_email(@user).deliver
+
+ format.html { redirect_to(@user, :notice => 'User was successfully created.') }
+ format.xml { render :xml => @user, :status => :created, :location => @user }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
+ end
+ end
end
end
</ruby>
-You can make a +app/observers+ directory and Rails will automatically load it for you (Rails will automatically load anything in the +app+ directory as of version 3.0)
-
-Now create a file called +user_observer.rb+ in +app/observers+ and make it look like:
-
-<ruby>
-class UserObserver < ActiveRecord::Observer
- def after_create(user)
- UserMailer.welcome_email(user).deliver
- end
-end
-</ruby>
+This provides a much simpler implementation that does not require the registering of observers and the like.
-Notice how we call <tt>UserMailer.welcome_email(user)</tt>? Even though in the <tt>user_mailer.rb</tt> file we defined an instance method, we are calling the method_name +welcome_email(user)+ on the class. This is a peculiarity of Action Mailer.
+The method +welcome_email+ returns a Mail::Message object which can then just be told +deliver+ to send itself out.
NOTE: In previous versions of Rails, you would call +deliver_welcome_email+ or +create_welcome_email+ however in Rails 3.0 this has been deprecated in favour of just calling the method name itself.
-The method +welcome_email+ returns a Mail::Message object which can then just be told +deliver+ to send itself out.
-
+WARNING: Sending out one email should only take a fraction of a second, if you are planning on sending out many emails, or you have a slow domain resolution service, you might want to investigate using a background process like delayed job.
h4. Complete List of Action Mailer Methods
@@ -160,21 +163,23 @@ Defining custom headers are simple, you can do it one of three ways:
* Defining a header field as a parameter to the +mail+ method:
<ruby>
-mail(:x_spam => value)
+mail("X-Spam" => value)
</ruby>
* Passing in a key value assignment to the +headers+ method:
<ruby>
-headers[:x_spam] = value
+headers["X-Spam"] = value
</ruby>
* Passing a hash of key value pairs to the +headers+ method:
<ruby>
-headers {:x_spam => value, :x_special => another_value}
+headers {"X-Spam" => value, "X-Special" => another_value}
</ruby>
+TIP: All <tt>X-Value</tt> headers per the RFC2822 can appear more than one time. If you want to delete an <tt>X-Value</tt> header, you need to assign it a value of <tt>nil</tt>.
+
h5. Adding Attachments
Adding attachments has been simplified in Action Mailer 3.0.
@@ -325,7 +330,7 @@ class UserMailer < ActionMailer::Base
end
</ruby>
-The above will send a multipart email with an attachment, properly nested with the top level being <tt>mixed/multipart</tt> and the first part being a <tt>mixed/alternative</tt> containing the plain text and HTML email messages.
+The above will send a multipart email with an attachment, properly nested with the top level being <tt>multipart/mixed</tt> and the first part being a <tt>multipart/alternative</tt> containing the plain text and HTML email messages.
h3. Receiving Emails
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index 050486a5a4..70b88db3a4 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -752,6 +752,7 @@ h3. Building Complex Forms
Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
+* As of Rails 2.3, Rails includes "Nested Attributes":./2_3_release_notes.html#nested-attributes and "Nested Object Forms":./2_3_release_notes.html#nested-object-forms
* Ryan Bates' series of Railscasts on "complex forms":http://railscasts.com/episodes/75
* Handle Multiple Models in One Form from "Advanced Rails Recipes":http://media.pragprog.com/titles/fr_arr/multiple_models_one_form.pdf
* Eloy Duran's "complex-forms-examples":http://github.com/alloy/complex-form-examples/ application
diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile
index 01e3380ee4..dcad451e23 100644
--- a/railties/guides/source/i18n.textile
+++ b/railties/guides/source/i18n.textile
@@ -129,7 +129,7 @@ However, you would probably like to *provide support for more locales* in your a
WARNING: You may be tempted to store the chosen locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being "_RESTful_":http://en.wikipedia.org/wiki/Representational_State_Transfer. Read more about the RESTful approach in "Stefan Tilkov's articles":http://www.infoq.com/articles/rest-introduction. There may be some exceptions to this rule, which are discussed below.
-The _setting part_ is easy. You can set the locale in a +before_filter+ in the ApplicationController like this:
+The _setting part_ is easy. You can set the locale in a +before_filter+ in the +ApplicationController+ like this:
<ruby>
before_filter :set_locale
@@ -158,7 +158,7 @@ You can implement it like this in your +ApplicationController+:
before_filter :set_locale
def set_locale
- I18n.locale = extract_locale_from_uri
+ I18n.locale = extract_locale_from_tld
end
# Get locale from top-level domain or return nil if such locale is not available
@@ -206,7 +206,7 @@ Getting the locale from +params+ and setting it accordingly is not hard; includi
Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its "+ApplicationController#default_url_options+":http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for "+url_for+":http://api.rubyonrails.org/classes/ActionController/Base.html#M000503 and helper methods dependent on it (by implementing/overriding this method).
-We can include something like this in our ApplicationController then:
+We can include something like this in our +ApplicationController+ then:
<ruby>
# app/controllers/application_controller.rb
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index a8c7ce0865..9182f89f5b 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -1792,487 +1792,53 @@ Now that Rails has finished loading all the Railties by way of +require 'rails/a
NOTE: It is worth mentioning here that you are not tied to using Bundler with Rails 3, but it is (of course) advised that you do. To "turn off" Bundler, comment out or remove the corresponding lines in _config/application.rb_ and _config/boot.rb_.
-Bundler was +require+'d back in _config/boot.rb_ and now we'll dive into the internals of Bundler to determine precisely what this line accomplishes.
+Bundler was +require+'d back in _config/boot.rb_, and so that is what makes it available here. This guide does not dive into the internals of Bundler; it's really it's own separate guide.
-h4. +Bundler.require+
+The +Bundler.require+ method adds all the gems not specified inside a +group+ in the +Gemfile+ and the ones specified in groups for the +Rails.env+ (in this case, _development_), to the load path. This is how an application is able to find them.
-+Bundler.require+ is defined in _lib/bundler.rb_:
+The rest of this file is spent defining your application's main class. This is it without the comments:
<ruby>
- def require(*groups)
- gemfile = default_gemfile
- load(gemfile).require(*groups)
- end
-</ruby>
-
-The +groups+ variable here would be a two-element array of the arguments passed to +Bundler.require+. In this case we're going to assume, +Rails.env+ is +"development"+.
-
-h4. Locating the Gemfile
-
-+default_gemfile+ is defined in _lib/bundler.rb_ and makes a call out to the +SharedHelpers+ module:
-
-<ruby>
- def default_gemfile
- SharedHelpers.default_gemfile
- end
-</ruby>
-
-+SharedHelpers+ defines +default_gemfile+ like this:
-
-<ruby>
- def default_gemfile
- gemfile = find_gemfile
- gemfile or raise GemfileNotFound, "The default Gemfile was not found"
- Pathname.new(gemfile)
- end
-</ruby>
-
-+find_gemfile+ is defined like this:
-
-<ruby>
- def find_gemfile
- return ENV['BUNDLE_GEMFILE'] if ENV['BUNDLE_GEMFILE']
-
- previous = nil
- current = File.expand_path(Dir.pwd)
-
- until !File.directory?(current) || current == previous
- filename = File.join(current, 'Gemfile')
- return filename if File.file?(filename)
- current, previous = File.expand_path("..", current), current
- end
- end
-</ruby>
-
-The first line of course means if you define the environment variable +BUNDLE_GEMFILE+ this is the name of the file that will be used and returned. If not, then Bundler will look for a file called _Gemfile_ in the current directory and if it can find it then it will return the filename. If it cannot, it will recurse up the directory structure until it does. Once the file is found a +Pathname+ is made from the expanded path to _Gemfile_.
-
-If the file cannot be found at all then +GemfileNotFound+ will be raised back in +default_gemfile+.
-
-h4. Loading the Gemfile
-
-Now that Bundler has determined what the _Gemfile_ is, it goes about loading it:
-
-<ruby>
- def require(*groups)
- gemfile = default_gemfile
- load(gemfile).require(*groups)
- end
-</ruby>
-
-+load+ is defined like this in _lib/bundler.rb_:
-
-<ruby>
- def load(gemfile = default_gemfile)
- root = Pathname.new(gemfile).dirname
- Runtime.new root, definition(gemfile)
- end
-</ruby>
-
-The next method to be called here would be +definition+ and it is defined like this:
-
-<ruby>
- def definition(gemfile = default_gemfile)
- configure
- root = Pathname.new(gemfile).dirname
- lockfile = root.join("Gemfile.lock")
- if lockfile.exist?
- Definition.from_lock(lockfile)
- else
- Definition.from_gemfile(gemfile)
- end
- end
-</ruby>
-
-+configure+ is responsible for setting up the path to gem home and gem path:
-
-<ruby>
- def configure
- @configured ||= begin
- configure_gem_home_and_path
- true
- end
- end
-</ruby>
-
-+configure_gem_home_and_path+ defined like this:
-
-<ruby>
- def configure_gem_home_and_path
- if settings[:disable_shared_gems]
- ENV['GEM_HOME'] = File.expand_path(bundle_path, root)
- ENV['GEM_PATH'] = ''
- else
- gem_home, gem_path = Gem.dir, Gem.path
- ENV["GEM_PATH"] = [gem_home, gem_path].flatten.compact.join(File::PATH_SEPARATOR)
- ENV["GEM_HOME"] = bundle_path.to_s
- end
-
- Gem.clear_paths
- end
-</ruby>
-
-We do not have +settings[:disabled_shared_gems]+ set to true so this will execute the code under the +else+. The +ENV["GEM_PATH"]+ will resemble +/usr/local/lib/ruby/gems/1.9.1:/home/you/.gem/ruby/1.9.1+
-
-And +ENV["GEM_HOME"]+ will be the path to the gems installed into your home directory by Bundler, something resembling +/home/you/.bundle/ruby/1.9.1+.
-
-After +configure_gem_home_and_path+ is done the +definition+ method goes about creating a +Definition+ from either +Gemfile.lock+ if it exists, or the +gemfile+ previously located. +Gemfile.lock+ only exists if +bundle lock+ has been ran and so far it has not.
-
-+Definition.from_gemfile+ is defined in _lib/bundler/definition.rb_:
-
-<ruby>
- def self.from_gemfile(gemfile)
- gemfile = Pathname.new(gemfile).expand_path
-
- unless gemfile.file?
- raise GemfileNotFound, "#{gemfile} not found"
- end
-
- Dsl.evaluate(gemfile)
- end
-</ruby>
-
-Now that the +gemfile+ is located +Dsl.evaluate+ goes about loading it. The code for this can be found in _lib/bundler/dsl.rb_:
-
-<ruby>
- def self.evaluate(gemfile)
- builder = new
- builder.instance_eval(File.read(gemfile.to_s), gemfile.to_s, 1)
- builder.to_definition
- end
-</ruby>
-
-+new+ here will, of course, call +initialize+ which sets up a couple of variables:
-
-<ruby>
- def initialize
- @source = nil
- @sources = []
- @dependencies = []
- @group = nil
- end
-</ruby>
-
-When Bundler calls +instance_eval+ on the new +Bundler::Dsl+ object it evaluates the content of the +gemfile+ file within the context of this instance. The Gemfile for a default Rails 3 project with all the comments stripped out looks like this:
-
-<ruby>
- source 'http://rubygems.org'
-
- gem 'rails', '3.0.0.beta1'
-
- # Bundle edge Rails instead:
- # gem 'rails', :git => 'git://github.com/rails/rails.git'
-
- gem 'sqlite3-ruby', :require => 'sqlite3'
-</ruby>
-
-When Bundler loads this file it firstly calls the +source+ method on the +Bundler::Dsl+ object:
-
-<ruby>
- def source(source, options = {})
- @source = case source
- when :gemcutter, :rubygems, :rubyforge then Source::Rubygems.new("uri" => "http://gemcutter.org")
- when String then Source::Rubygems.new("uri" => source)
- else source
- end
-
- options[:prepend] ? @sources.unshift(@source) : @sources << @source
-
- yield if block_given?
- @source
- ensure
- @source = nil
- end
-</ruby>
-
-TODO: Perhaps make this a side-note. However you do that.
-
-The interesting thing to note about this method is that it takes a block, so you may do:
-
-<ruby>
- source 'http://someothergemhost.com' do
- gem 'your_favourite_gem'
- end
-</ruby>
-
-if you wish to install _your_favourite_gem_ from _http://someothergemhost.com_.
-
-In this instance however a block is not specified so this sets up the +@source+ instance variable to be +'http://rubygems.org'+.
-
-The next method that is called is +gem+:
-
-<ruby>
- def gem(name, *args)
- options = Hash === args.last ? args.pop : {}
- version = args.last || ">= 0"
- if options[:group]
- options[:group] = options[:group].to_sym
+ module YourApp
+ class Application < Rails::Application
+ config.encoding = "utf-8"
+ config.filter_parameters += [:password]
end
-
- _deprecated_options(options)
- _normalize_options(name, version, options)
-
- @dependencies << Dependency.new(name, version, options)
end
</ruby>
-This sets up a couple of important things initially. If you specify a gem like the following:
-
-<ruby>
- gem 'rails', "2.3.4"
-</ruby>
-
-This sets +options+ to be an empty hash, but +version+ to be +"2.3.4"+. TODO: How does one pass options and versions at the same time?
+h3. Return to Rails
-In the Gemfile for a default Rails project, the first +gem+ line is:
+On the surface, this looks like a simple class inheritance. There's more underneath though. back in +Rails::Application+, the +inherited+ method is defined:
<ruby>
- gem 'rails', '3.0.0.beta2'
-</ruby>
-
-TODO: change version number.
-
-This line will check that +options+ contains no deprecated options by using the +_deprecated_options+ method, but the +options+ hash is empty. This is of course until +_normalize_options+ has its way:
-
-<ruby>
- def _normalize_options(name, version, opts)
- _normalize_hash(opts)
-
- group = opts.delete("group") || @group
-
- # Normalize git and path options
- ["git", "path"].each do |type|
- if param = opts[type]
- options = _version?(version) ? opts.merge("name" => name, "version" => version) : opts.dup
- source = send(type, param, options, :prepend => true)
- opts["source"] = source
- end
- end
-
- opts["source"] ||= @source
-
- opts["group"] = group
+ def inherited(base)
+ raise "You cannot have more than one Rails::Application" if Rails.application
+ super
+ Rails.application = base.instance
end
</ruby>
-+_normalize_hash+ will convert all the keys in the +opts+ hash to strings. There is neither a +git+ or a +path+ key in the +opts+ hash so the next couple of lines are ignored, then the +source+ and +group+ keys are set up.
-
-TODO: Maybe it is best to cover what would happen in the case these lines did exist?
-
-The next line goes about defining a dependency for this gem:
-
-<ruby>
- @dependencies << Dependency.new(name, version, options)
-</ruby>
-
-This class is defined like this:
+We do not already have a +Rails.application+, so instead this resorts to calling +super+. +Rails::Application+ descends from +Rails::Engine+ and so will call the +inherited+ method in +Rails::Engine+, but before that it's important to note that +called_from+ is defined an +attr_accessor+ on +Rails::Engine+:
<ruby>
- module Bundler
- class Dependency < Gem::Dependency
- attr_reader :autorequire
- attr_reader :groups
-
- def initialize(name, version, options = {}, &blk)
- super(name, version)
-
- @autorequire = nil
- @groups = Array(options["group"] || :default).map { |g| g.to_sym }
- @source = options["source"]
-
- if options.key?('require')
- @autorequire = Array(options['require'] || [])
- end
+ def inherited(base)
+ unless base.abstract_railtie?
+ base.called_from = begin
+ # Remove the line number from backtraces making sure we don't leave anything behind
+ call_stack = caller.map { |p| p.split(':')[0..-2].join(':') }
+ File.dirname(call_stack.detect { |p| p !~ %r[railties[\w\-\.]*/lib/rails|rack[\w\-\.]*/lib/rack] })
end
end
- end
-</ruby>
-
-The +initialize+ method in +Gem::Dependency+ is defined:
-
-<ruby>
- def initialize(name, version_requirements, type=:runtime)
- @name = name
- unless TYPES.include? type
- raise ArgumentError, "Valid types are #{TYPES.inspect}, not #{@type.inspect}"
- end
- @type = type
- @version_requirements = Gem::Requirement.create version_requirements
- @version_requirement = nil # Avoid warnings.
- end
-</ruby>
-
-The +version_requirements+ that was passed in here will be inspected by +Gem::Requirement.create+ and return, for our +3.0.0beta2+ version string a +Gem::Requirement+ object:
-
-<ruby>
- #<Gem::Requirement:0x101dd8c20 @requirements=[["=", #<Gem::Version "3.0.0beta2">]]>
-</ruby>
-
-Going back to +Bundler::Dependency+, the next line simply sets +@autorequire+ to +nil+ and the next line is a little more interesting:
-
-<ruby>
- @autorequire = nil
- @groups = Array(options["group"] || :default).map { |g| g.to_sym }
-</ruby>
-
-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:
-
-<ruby>
- group :test, :cucumber do
- gem 'faker'
- end
-</ruby>
-
-The final lines in +initialize+ work on the +require+ option which is not passed:
-
-<ruby>
- if options.key?('require')
- @autorequire = Array(options['require'] || [])
- end
-</ruby>
-
-If it were to be used in the _Gemfile_, it would look like this:
-
-<ruby>
- gem 'thinking-sphinx', :require => "thinking_sphinx"
-</ruby>
-
-So far, this is what simply loading the _Gemfile_ does.
-
-h3. Bring forth the gems
-Now that the _Gemfile_ has finished being parsed, the next line is:
-
-<ruby>
- builder.to_definition
-</ruby>
-
-This method is defined in _lib/bundler/dsl.rb_ and does this:
-
-<ruby>
- def to_definition
- Definition.new(@dependencies, @sources)
- end
-</ruby>
-
-The +Bundler::Definition#initialize+ method is this:
-
-<ruby>
- def initialize(dependencies, sources)
- @dependencies = dependencies
- @sources = sources
- end
-</ruby>
-
-Now Bundler has a +Bundler::Definition+ object to be passed back to the +load+ method from _lib/bundler.rb_:
-
-<ruby>
- def load(gemfile = default_gemfile)
- root = Pathname.new(gemfile).dirname
- Runtime.new root, definition(gemfile)
- end
-</ruby>
-
-The +Bundler::Runtime+ class inherits from +Bundler::Environment+ and the reason this is pointed out is because +super+ is used in the +initialize+ method in +Bundler::Runtime+:
-
-<ruby>
- super
- if locked?
- write_rb_lock
- end
-</ruby>
-
-Thankfully, the +Bundler::Environment#initialize+ method is nothing too complex:
-
-<ruby>
- def initialize(root, definition)
- @root = root
- @definition = definition
- end
-</ruby>
-
-The +locked?+ method checks if the _Gemfile.lock_ or _.bundler/environment.rb_ files exist:
-
-<ruby>
- def locked?
- File.exist?("#{root}/Gemfile.lock") || File.exist?("#{root}/.bundle/environment.rb")
- end
-</ruby>
-
-And if they do will call +write_rb_lock+:
-
-<ruby>
- def write_rb_lock
- shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__))
- template = File.read(File.expand_path("../templates/environment.erb", __FILE__))
- erb = ERB.new(template, nil, '-')
- FileUtils.mkdir_p(rb_lock_file.dirname)
- File.open(rb_lock_file, 'w') do |f|
- f.puts erb.result(binding)
- end
- end
-</ruby>
-
-This will write out to _.bundler/environment.rb_ the state of the current environment.
-
-Now a quick refresher. Bundler is still evaulating the code for the +require+ in _lib/bundler.rb_, and the +groups+ variable here is an +Array+ containing two elements: +:default+ and the current Rails environment: +development+:
-
-<ruby>
- def require(*groups)
- gemfile = default_gemfile
- load(gemfile).require(*groups)
- end
-</ruby>
-
-The second +require+ method here:
-
-<ruby>
- load(gemfile).require(*groups)
-</ruby>
-
-Is defined on _bundler/runtime.rb_:
-
-<ruby>
- def require(*groups)
- groups.map! { |g| g.to_sym }
- groups = [:default] if groups.empty?
- autorequires = autorequires_for_groups(*groups)
-
- groups.each do |group|
- (autorequires[group] || [[]]).each do |path, explicit|
- if explicit
- Kernel.require(path)
- else
- begin
- Kernel.require(path)
- rescue LoadError
- end
- end
- end
- end
+ super
end
</ruby>
-This method does TODO: Describe what magic this undertakes.
-
-The first method to be called here is +autorequires_for_groups+:
-
-<ruby>
- def autorequires_for_groups(*groups)
- groups.map! { |g| g.to_sym }
- autorequires = Hash.new { |h,k| h[k] = [] }
-
- ordered_deps = []
- specs_for(*groups).each do |g|
- dep = @definition.dependencies.find{|d| d.name == g.name }
- ordered_deps << dep if dep && !ordered_deps.include?(dep)
- end
-</ruby>
+This +called_from+ setting looks a little overwhelming to begin with, but the short end of it is that it returns the route to your application's config directory, something like: _/home/you/yourapp/config_. After +called_from+ has been set, +super+ is again called and this means the +Rails::Railtie#inherited+ method.
+
-The +specs_for+ method here:
-<ruby>
-
-</ruby>
h3. Firing it up!
@@ -2642,7 +2208,7 @@ The method +find_with_root_flag+ is defined on +Rails::Engine+ (the superclass o
root = File.exist?("#{root_path}/#{flag}") ? root_path : default
raise "Could not find root path for #{self}" unless root
- RUBY_PLATFORM =~ /mswin|mingw/ ?
+ RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
Pathname.new(root).expand_path : Pathname.new(root).realpath
end
</ruby>