aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md27
-rw-r--r--railties/guides/code/getting_started/app/views/layouts/application.html.erb2
-rw-r--r--railties/guides/code/getting_started/config/application.rb5
-rw-r--r--railties/guides/code/getting_started/config/environments/test.rb5
-rw-r--r--railties/guides/source/action_mailer_basics.textile15
-rw-r--r--railties/guides/source/active_record_querying.textile16
-rw-r--r--railties/guides/source/active_support_core_extensions.textile18
-rw-r--r--railties/guides/source/asset_pipeline.textile2
-rw-r--r--railties/guides/source/configuring.textile5
-rw-r--r--railties/guides/source/contributing_to_ruby_on_rails.textile2
-rw-r--r--railties/guides/source/getting_started.textile4
-rw-r--r--railties/guides/source/i18n.textile2
-rw-r--r--railties/guides/source/initialization.textile22
-rw-r--r--railties/guides/source/migrations.textile4
-rw-r--r--railties/guides/source/testing.textile2
-rw-r--r--railties/lib/rails/application.rb31
-rw-r--r--railties/lib/rails/application/configuration.rb5
-rw-r--r--railties/lib/rails/application/route_inspector.rb37
-rw-r--r--railties/lib/rails/code_statistics.rb17
-rw-r--r--railties/lib/rails/commands/dbconsole.rb2
-rw-r--r--railties/lib/rails/commands/plugin.rb320
-rw-r--r--railties/lib/rails/engine.rb67
-rw-r--r--railties/lib/rails/generators/actions.rb7
-rw-r--r--railties/lib/rails/generators/app_base.rb1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt5
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb20
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt2
-rw-r--r--railties/lib/rails/railtie.rb2
-rw-r--r--railties/test/application/configuration_test.rb1
-rw-r--r--railties/test/application/console_test.rb1
-rw-r--r--railties/test/application/middleware/cookies_test.rb47
-rw-r--r--railties/test/application/rackup_test.rb2
-rw-r--r--railties/test/application/route_inspect_test.rb26
-rw-r--r--railties/test/generators/actions_test.rb8
-rw-r--r--railties/test/generators/app_generator_test.rb7
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb132
39 files changed, 626 insertions, 258 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 0c59f59917..6b0be4c096 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,20 +1,27 @@
## Rails 3.2.0 (unreleased) ##
+* Display mounted engine's routes in `rake routes`. *Piotr Sarnacki*
+
+* Allow to change the loading order of railties with `config.railties_order=` *Piotr Sarnacki*
+
+ Example:
+ config.railties_order = [Blog::Engine, :main_app, :all]
+
* Scaffold returns 204 No Content for API requests without content. This makes scaffold work with jQuery out of the box. *José Valim*
-* Updated Rails::Rack::Logger middleware to apply any tags set in config.log_tags to the newly ActiveSupport::TaggedLogging Rails.logger. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications *DHH*
+* Update Rails::Rack::Logger middleware to apply any tags set in config.log_tags to the newly ActiveSupport::TaggedLogging Rails.logger. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications *DHH*
* Default options to `rails new` can be set in ~/.railsrc *Guillermo Iguaran*
-* Added destroy alias to Rails engines. *Guillermo Iguaran*
+* Add destroy alias to Rails engines *Guillermo Iguaran*
-* Added destroy alias for Rails command line. This allows the following: `rails d model post`. *Andrey Ognevsky*
+* Add destroy alias for Rails command line. This allows the following: `rails d model post` *Andrey Ognevsky*
* Attributes on scaffold and model generators default to string. This allows the following: "rails g scaffold Post title body:text author" *José Valim*
-* Removed old plugin generator (`rails generate plugin`) in favor of `rails plugin new` command. *Guillermo Iguaran*
+* Remove old plugin generator (`rails generate plugin`) in favor of `rails plugin new` command *Guillermo Iguaran*
-* Removed old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API. *Guillermo Iguaran*
+* Remove old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API *Guillermo Iguaran*
* Rails 3.1.1
@@ -30,6 +37,16 @@
Plugins developers need to special case their initializers that are
meant to be run in the assets group by adding :group => :assets.
+## Rails 3.1.2 (unreleased) ##
+
+* Engines: don't blow up if db/seeds.rb is missing.
+
+ *Jeremy Kemper*
+
+* `rails new foo --skip-test-unit` should not add the `:test` task to the rake default task.
+ *GH 2564*
+
+ *José Valim*
## Rails 3.1.0 (August 30, 2011) ##
diff --git a/railties/guides/code/getting_started/app/views/layouts/application.html.erb b/railties/guides/code/getting_started/app/views/layouts/application.html.erb
index 1e1e4b9a99..7fd6b4f516 100644
--- a/railties/guides/code/getting_started/app/views/layouts/application.html.erb
+++ b/railties/guides/code/getting_started/app/views/layouts/application.html.erb
@@ -2,7 +2,7 @@
<html>
<head>
<title>Blog</title>
- <%= stylesheet_link_tag "application" %>
+ <%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
diff --git a/railties/guides/code/getting_started/config/application.rb b/railties/guides/code/getting_started/config/application.rb
index e914b5a80e..e16da30f72 100644
--- a/railties/guides/code/getting_started/config/application.rb
+++ b/railties/guides/code/getting_started/config/application.rb
@@ -39,6 +39,11 @@ module Blog
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
+ # Use SQL instead of Active Record's schema dumper when creating the database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
# Enable the asset pipeline
config.assets.enabled = true
diff --git a/railties/guides/code/getting_started/config/environments/test.rb b/railties/guides/code/getting_started/config/environments/test.rb
index 833241ace3..08697cbbc9 100644
--- a/railties/guides/code/getting_started/config/environments/test.rb
+++ b/railties/guides/code/getting_started/config/environments/test.rb
@@ -29,11 +29,6 @@ Blog::Application.configure do
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
- # Use SQL instead of Active Record's schema dumper when creating the test database.
- # This is necessary if your schema can't be completely dumped by the schema dumper,
- # like if you have constraints or database-specific column types
- # config.active_record.schema_format = :sql
-
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index ad5b848d2c..26c95be031 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -362,21 +362,14 @@ When using named routes you only need to supply the +:host+:
Email clients have no web context and so paths have no base URL to form complete web addresses. Thus, when using named routes only the "_url" variant makes sense.
-It is also possible to set a default host that will be used in all mailers by setting the +:host+ option in the +ActionMailer::Base.default_url_options+ hash as follows:
+It is also possible to set a default host that will be used in all mailers by setting the <tt>:host</tt> option as a configuration option in <tt>config/application.rb</tt>:
<ruby>
-class UserMailer < ActionMailer::Base
- default_url_options[:host] = "example.com"
-
- def welcome_email(user)
- @user = user
- @url = user_url(@user)
- mail(:to => user.email,
- :subject => "Welcome to My Awesome Site")
- end
-end
+config.action_mailer.default_url_options = { :host => "example.com" }
</ruby>
+If you use this setting, you should pass the <tt>:only_path => false</tt> option when using +url_for+. This will ensure that absolute URLs are generated because the +url_for+ view helper will, by default, generate relative URLs when a <tt>:host</tt> option isn't explicitly provided.
+
h4. Sending Multipart Emails
Action Mailer will automatically send multipart emails if you have different templates for the same action. So, for our UserMailer example, if you have +welcome_email.text.erb+ and +welcome_email.html.erb+ in +app/views/user_mailer+, Action Mailer will automatically send a multipart email with the HTML and text versions setup as different parts.
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index ad12dca7e8..c4724f182e 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -1287,6 +1287,7 @@ User.where(:id => 1).joins(:posts).explain
may yield
<plain>
+EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus>
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus>
@@ -1302,6 +1303,7 @@ Active Record performs a pretty printing that emulates the one of the database
shells. So, the same query running with the PostgreSQL adapter would yield instead
<plain>
+EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE "users"."id" = 1
QUERY PLAN
------------------------------------------------------------------------------
Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0)
@@ -1324,12 +1326,15 @@ User.where(:id => 1).includes(:posts).explain
yields
<plain>
+EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus>
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus>
| 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus>
1 row in set (0.00 sec)
+
+EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` IN (1)
<plus>----<plus>-------------<plus>-------<plus>------<plus>---------------<plus>------<plus>---------<plus>------<plus>------<plus>-------------<plus>
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
<plus>----<plus>-------------<plus>-------<plus>------<plus>---------------<plus>------<plus>---------<plus>------<plus>------<plus>-------------<plus>
@@ -1339,3 +1344,14 @@ yields
</plain>
under MySQL.
+
+h4. Interpreting EXPLAIN
+
+Interpretation of the output of EXPLAIN is beyond the scope of this guide. The
+following pointers may be helpful:
+
+* SQLite3: "EXPLAIN QUERY PLAN":http://www.sqlite.org/eqp.html
+
+* MySQL: "EXPLAIN Output Format":http://dev.mysql.com/doc/refman/5.6/en/explain-output.html
+
+* PostgreSQL: "Using EXPLAIN":http://www.postgresql.org/docs/current/static/using-explain.html
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index ff6c5f967f..c1046a3b63 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -440,14 +440,16 @@ NOTE: Defined in +active_support/core_ext/kernel/reporting.rb+.
h4. +in?+
-The predicate +in?+ tests if an object is included in another object. An +ArgumentError+ exception will be raised if the argument passed does not respond to +include?+.
+The predicate +in?+ tests if an object is included in another object or a list of objects. An +ArgumentError+ exception will be raised if a single argument is passed and it does not respond to +include?+.
Examples of +in?+:
<ruby>
+1.in?(1,2) # => true
1.in?([1,2]) # => true
"lo".in?("hello") # => true
25.in?(30..50) # => false
+1.in?(1) # => ArgumentError
</ruby>
NOTE: Defined in +active_support/core_ext/object/inclusion.rb+.
@@ -571,7 +573,7 @@ NOTE: Defined in +active_support/core_ext/module/attr_accessor_with_default.rb+.
h5. Internal Attributes
-When you are defining an attribute in a class that is meant to be subclassed name collisions are a risk. That's remarkably important for libraries.
+When you are defining an attribute in a class that is meant to be subclassed, name collisions are a risk. That's remarkably important for libraries.
Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby built-in +attr_*+ counterparts, except they name the underlying instance variable in a way that makes collisions less likely.
@@ -3039,12 +3041,16 @@ Active Support defines these methods as well for Ruby 1.8.
h6. +beginning_of_week+, +end_of_week+
-The methods +beginning_of_week+ and +end_of_week+ return the dates for the beginning and end of week, assuming weeks start on Monday:
+The methods +beginning_of_week+ and +end_of_week+ return the dates for the
+beginning and end of the week, respectively. Weeks are assumed to start on
+Monday, but that can be changed passing an argument, see examples:
<ruby>
-d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
-d.beginning_of_week # => Mon, 03 May 2010
-d.end_of_week # => Sun, 09 May 2010
+d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
+d.beginning_of_week # => Mon, 03 May 2010
+d.beginning_of_week(:sunday) # => Sun, 02 May 2010
+d.end_of_week # => Sun, 09 May 2010
+d.end_of_week(:sunday) # => Sat, 08 May 2010
</ruby>
+beginning_of_week+ is aliased to +monday+ and +at_beginning_of_week+. +end_of_week+ is aliased to +sunday+ and +at_end_of_week+.
diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile
index 6ff5e87b6d..3681501293 100644
--- a/railties/guides/source/asset_pipeline.textile
+++ b/railties/guides/source/asset_pipeline.textile
@@ -438,7 +438,7 @@ location ~ ^/assets/ {
}
</plain>
-When files are precompiled, Sprockets also creates a "gzipped":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. Web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once Sprockets uses the maximum compression ratio, thus reducing the size of the data transfer to the minimum. On the other hand, web servers can be configured to serve compressed content directly from disk, rather than deflating non-compressed files themselves.
+When files are precompiled, Sprockets also creates a "gzipped":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. Web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once, Sprockets uses the maximum compression ratio, thus reducing the size of the data transfer to the minimum. On the other hand, web servers can be configured to serve compressed content directly from disk, rather than deflating non-compressed files themselves.
Nginx is able to do this automatically enabling +gzip_static+:
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index cd6e7d116e..d91011c370 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -88,6 +88,8 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is
* +config.log_level+ defines the verbosity of the Rails logger. This option defaults to +:debug+ for all modes except production, where it defaults to +:info+.
+* +config.log_tags+ accepts a list of methods that respond to +request+ object. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications.
+
* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby +Logger+ class. Defaults to an instance of +ActiveSupport::BufferedLogger+, with auto flushing off in production mode.
* +config.middleware+ allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware":#configuring-middleware section below.
@@ -188,6 +190,7 @@ Every Rails application comes with a standard set of middleware which it uses in
* +Rack::Runtime+ sets an +X-Runtime+ header, containing the time (in seconds) taken to execute the request.
* +Rails::Rack::Logger+ notifies the logs that the request has began. After request is complete, flushes all the logs.
* +ActionDispatch::ShowExceptions+ rescues any exception returned by the application and renders nice exception pages if the request is local or if +config.consider_all_requests_local+ is set to +true+. If +config.action_dispatch.show_exceptions+ is set to +false+, exceptions will be raised regardless.
+* +ActionDispatch::RequestId+ makes a unique X-Request-Id header available to the response and enables the +ActionDispatch::Request#uuid+ method.
* +ActionDispatch::RemoteIp+ checks for IP spoofing attacks. Configurable with the +config.action_dispatch.ip_spoofing_check+ and +config.action_dispatch.trusted_proxies+ settings.
* +Rack::Sendfile+ intercepts responses whose body is being served from a file and replaces it with a server specific X-Sendfile header. Configurable with +config.action_dispatch.x_sendfile_header+.
* +ActionDispatch::Callbacks+ runs the prepare callbacks before serving the request.
@@ -263,6 +266,8 @@ h4. Configuring Active Record
* +config.active_record.whitelist_attributes+ will create an empty whitelist of attributes available for mass-assignment security for all models in your app.
+* +config.active_record.identity_map+ controls whether the identity map is enabled, and is false by default.
+
The MySQL adapter adds one additional configuration option:
* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether Active Record will consider all +tinyint(1)+ columns in a MySQL database to be booleans and is true by default.
diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile
index 1cd70404a3..37ead2bff2 100644
--- a/railties/guides/source/contributing_to_ruby_on_rails.textile
+++ b/railties/guides/source/contributing_to_ruby_on_rails.textile
@@ -215,7 +215,7 @@ TIP: You may want to "put your git branch name in your shell prompt":http://qugs
h3. Helping to Resolve Existing Issues
-As a next step beyond reporting issues, you can help the core team resolve existing issues. If you check the "Everyone's Issues":https://github.com/rails/rails/issues?sort=created&direction=desc&state=open list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:
+As a next step beyond reporting issues, you can help the core team resolve existing issues. If you check the "Everyone's Issues":https://github.com/rails/rails/issues list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:
h4. Verifying Bug Reports
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index fde83ae730..fe43c9db36 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -248,7 +248,7 @@ the following:
$ rails --version
</shell>
-If it says something like "Rails 3.1.1" you are ready to continue.
+If it says something like "Rails 3.1.3" you are ready to continue.
h4. Creating the Blog Application
@@ -450,6 +450,8 @@ start a web server on your development machine. You can do this by running:
$ rails server
</shell>
+TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and the absence of a runtime will give you an +execjs+ error. Usually Mac OS X and Windows come with a JavaScript runtime installed. +therubyracer+ and +therubyrhino+ are the commonly used runtimes for Ruby and JRuby respectively. You can also investigate a list of runtimes at "ExecJS":https://github.com/sstephenson/execjs.
+
This will fire up an instance of the WEBrick web server by default (Rails can
also use several other web servers). To see your application in action, open a
browser window and navigate to "http://localhost:3000":http://localhost:3000.
diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile
index 2d4cc13571..e9477e84cf 100644
--- a/railties/guides/source/i18n.textile
+++ b/railties/guides/source/i18n.textile
@@ -231,7 +231,7 @@ end
Now, when you call the +books_path+ method you should get +"/en/books"+ (for the default locale). An URL like +http://localhost:3001/nl/books+ should load the Netherlands locale, then, and following calls to +books_path+ should return +"/nl/books"+ (because the locale changed).
-If you don't want to force the use of a locale in your routes you can use an optional path scope (donated by the use brackets) like so:
+If you don't want to force the use of a locale in your routes you can use an optional path scope (denoted by the parentheses) like so:
<ruby>
# config/routes.rb
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 036b356a37..5ae9cf0f2b 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -17,7 +17,7 @@ As of Rails 3, +script/server+ has become +rails server+. This was done to centr
h4. +bin/rails+
-The actual +rails+ command is kept in _bin/rails_ at the and goes like this:
+The actual +rails+ command is kept in _bin/rails_:
<ruby>
#!/usr/bin/env ruby
@@ -31,7 +31,7 @@ rescue LoadError
end
</ruby>
-This file will attempt to load +rails/cli+ and if it cannot find it then add the +railties/lib+ path to the load path (+$:+) and will then try to require it again.
+This file will attempt to load +rails/cli+. If it cannot find it then +railties/lib+ is added to the load path (+$:+) before retrying.
h4. +railties/lib/rails/cli.rb+
@@ -56,7 +56,7 @@ else
end
</ruby>
-The +rbconfig+ file here is out of Ruby's standard library and provides us with the +RbConfig+ class which contains useful information dependent on how Ruby was compiled. We'll see this in use in +railties/lib/rails/script_rails_loader+.
+The +rbconfig+ file from the Ruby standard library provides us with the +RbConfig+ class which contains detailed information about the Ruby environment, including how Ruby was compiled. We can see this in use in +railties/lib/rails/script_rails_loader+.
<ruby>
require 'pathname'
@@ -71,7 +71,7 @@ module Rails
end
</ruby>
-The +rails/script_rails_loader+ file uses +RbConfig::Config+ to gather up the +bin_dir+ and +ruby_install_name+ values for the configuration which will result in a path such as +/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby+, which is the default path on Mac OS X. If you're running Windows the path may be something such as +C:/Ruby192/bin/ruby+. Anyway, the path on your system may be different, but the point of this is that it will point at the known ruby executable location for your install. The +RbConfig::CONFIG["EXEEXT"]+ will suffix this path with ".exe" if the script is running on Windows. This constant is used later on in +exec_script_rails!+. As for the +SCRIPT_RAILS+ constant, we'll see that when we get to the +in_rails_application?+ method.
+The +rails/script_rails_loader+ file uses +RbConfig::Config+ to obtain the +bin_dir+ and +ruby_install_name+ values for the configuration which together form the path to the Ruby interpreter. The +RbConfig::CONFIG["EXEEXT"]+ will suffix this path with ".exe" if the script is running on Windows. This constant is used later on in +exec_script_rails!+. As for the +SCRIPT_RAILS+ constant, we'll see that when we get to the +in_rails_application?+ method.
Back in +rails/cli+, the next line is this:
@@ -79,7 +79,7 @@ Back in +rails/cli+, the next line is this:
Rails::ScriptRailsLoader.exec_script_rails!
</ruby>
-This method is defined in +rails/script_rails_loader+ like this:
+This method is defined in +rails/script_rails_loader+:
<ruby>
def self.exec_script_rails!
@@ -96,7 +96,7 @@ rescue SystemCallError
end
</ruby>
-This method will first check if the current working directory (+cwd+) is a Rails application or is a subdirectory of one. The way to determine this is defined in the +in_rails_application?+ method like this:
+This method will first check if the current working directory (+cwd+) is a Rails application or a subdirectory of one. This is determined by the +in_rails_application?+ method:
<ruby>
def self.in_rails_application?
@@ -104,7 +104,7 @@ def self.in_rails_application?
end
</ruby>
-The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+, then +in_rails_application_subdirectory?+ will be used:
+The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+ then +in_rails_application_subdirectory?+ will be used:
<ruby>
def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
@@ -112,17 +112,17 @@ def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
end
</ruby>
-This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory is reached which contains this file then this line will run:
+This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory containing this file is reached then this line will run:
<ruby>
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
</ruby>
-This is effectively the same as doing +ruby script/rails [arguments]+. Where +[arguments]+ at this point in time is simply "server".
+This is effectively the same as running +ruby script/rails [arguments]+, where +[arguments]+ at this point in time is simply "server".
h4. +script/rails+
-This file looks like this:
+This file is as follows:
<ruby>
APP_PATH = File.expand_path('../../config/application', __FILE__)
@@ -130,7 +130,7 @@ require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
</ruby>
-The +APP_PATH+ constant here will be used later in +rails/commands+. The +config/boot+ file that +script/rails+ references is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
+The +APP_PATH+ constant will be used later in +rails/commands+. The +config/boot+ file referenced here is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
h4. +config/boot.rb+
diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile
index 23e36b39f9..c63f2aa119 100644
--- a/railties/guides/source/migrations.textile
+++ b/railties/guides/source/migrations.textile
@@ -658,7 +658,7 @@ In many ways this is exactly what it is. This file is created by inspecting the
There is however a trade-off: +db/schema.rb+ cannot express database specific items such as foreign key constraints, triggers, or stored procedures. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this, then you should set the schema format to +:sql+.
-Instead of using Active Record's schema dumper, the database's structure will be dumped using a tool specific to the database (via the +db:structure:dump+ Rake task) into +db/#{Rails.env}_structure.sql+. For example, for the PostgreSQL RDBMS, the +pg_dump+ utility is used. For MySQL, this file will contain the output of +SHOW CREATE TABLE+ for the various tables. Loading these schemas is simply a question of executing the SQL statements they contain. By definition, this will create a perfect copy of the database's structure. Using the +:sql+ schema format will, however, prevent loading the schema into a RDBMS other than the one used to create it.
+Instead of using Active Record's schema dumper, the database's structure will be dumped using a tool specific to the database (via the +db:structure:dump+ Rake task) into +db/structure.sql+. For example, for the PostgreSQL RDBMS, the +pg_dump+ utility is used. For MySQL, this file will contain the output of +SHOW CREATE TABLE+ for the various tables. Loading these schemas is simply a question of executing the SQL statements they contain. By definition, this will create a perfect copy of the database's structure. Using the +:sql+ schema format will, however, prevent loading the schema into a RDBMS other than the one used to create it.
h4. Schema Dumps and Source Control
@@ -670,4 +670,4 @@ The Active Record way claims that intelligence belongs in your models, not in th
Validations such as +validates :foreign_key, :uniqueness => true+ are one way in which models can enforce data integrity. The +:dependent+ option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level, these cannot guarantee referential integrity and so some people augment them with foreign key constraints.
-Although Active Record does not provide any tools for working directly with such features, the +execute+ method can be used to execute arbitrary SQL. There are also a number of plugins such as "foreign_key_migrations":https://github.com/harukizaemon/redhillonrails/tree/master/foreign_key_migrations/ which add foreign key support to Active Record (including support for dumping foreign keys in +db/schema.rb+).
+Although Active Record does not provide any tools for working directly with such features, the +execute+ method can be used to execute arbitrary SQL. You could also use some plugin like "foreigner":https://github.com/matthuhiggins/foreigner which add foreign key support to Active Record (including support for dumping foreign keys in +db/schema.rb+).
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index 2341a3522c..5dbbe2c0f0 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -927,7 +927,7 @@ class UserControllerTest < ActionController::TestCase
assert_difference 'ActionMailer::Base.deliveries.size', +1 do
post :invite_friend, :email => 'friend@example.com'
end
- invite_email = ActionMailer::Base.deliveries.first
+ invite_email = ActionMailer::Base.deliveries.last
assert_equal "You have been invited by me@example.com", invite_email.subject
assert_equal 'friend@example.com', invite_email.to[0]
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 82fffe86bb..25ff74506a 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -123,10 +123,33 @@ module Rails
@env_config ||= super.merge({
"action_dispatch.parameter_filter" => config.filter_parameters,
"action_dispatch.secret_token" => config.secret_token,
- "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions
+ "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
+ "action_dispatch.logger" => Rails.logger
})
end
+ def ordered_railties
+ @ordered_railties ||= begin
+ order = config.railties_order.map do |railtie|
+ if railtie == :main_app
+ self
+ elsif railtie.respond_to?(:instance)
+ railtie.instance
+ else
+ railtie
+ end
+ end
+
+ all = (railties.all - order)
+ all.push(self) unless all.include?(self)
+ order.push(:all) unless order.include?(:all)
+
+ index = order.index(:all)
+ order[index] = all
+ order.reverse.flatten
+ end
+ end
+
def initializers
Bootstrap.initializers_for(self) +
super +
@@ -141,6 +164,10 @@ module Rails
self
end
+ def helpers_paths
+ config.helpers_paths
+ end
+
protected
alias :build_middleware_stack :app
@@ -166,7 +193,7 @@ module Rails
middleware.use ::Rack::MethodOverride
middleware.use ::ActionDispatch::RequestId
middleware.use ::Rails::Rack::Logger, config.log_tags # must come after Rack::MethodOverride to properly log overridden methods
- middleware.use ::ActionDispatch::ShowExceptions, config.consider_all_requests_local
+ middleware.use ::ActionDispatch::ShowExceptions
middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies
if config.action_dispatch.x_sendfile_header.present?
middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 8f5b28faf8..e95b0f5495 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -10,8 +10,8 @@ module Rails
:dependency_loading, :filter_parameters,
:force_ssl, :helpers_paths, :logger, :log_tags, :preload_frameworks,
:reload_plugins, :secret_token, :serve_static_assets,
- :ssl_options, :static_cache_control, :session_options,
- :time_zone, :whiny_nils
+ :ssl_options, :static_cache_control, :session_options,
+ :time_zone, :whiny_nils, :railties_order
attr_writer :log_level
attr_reader :encoding
@@ -35,6 +35,7 @@ module Rails
@middleware = app_middleware
@generators = app_generators
@cache_store = [ :file_store, "#{root}/tmp/cache/" ]
+ @railties_order = [:all]
@assets = ActiveSupport::OrderedOptions.new
@assets.enabled = false
diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb
index 8252f21aa7..26652a8e5e 100644
--- a/railties/lib/rails/application/route_inspector.rb
+++ b/railties/lib/rails/application/route_inspector.rb
@@ -4,12 +4,23 @@ module Rails
# This class is just used for displaying route information when someone
# executes `rake routes`. People should not use this class.
class RouteInspector # :nodoc:
+ def initialize
+ @engines = ActiveSupport::OrderedHash.new
+ end
+
def format all_routes, filter = nil
if filter
all_routes = all_routes.select{ |route| route.defaults[:controller] == filter }
end
- routes = all_routes.collect do |route|
+ routes = collect_routes(all_routes)
+
+ formatted_routes(routes) +
+ formatted_routes_for_engines
+ end
+
+ def collect_routes(routes)
+ routes = routes.collect do |route|
route_reqs = route.requirements
rack_app = route.app unless route.app.class.name.to_s =~ /^ActionDispatch::Routing/
@@ -25,12 +36,32 @@ module Rails
verb = route.verb.source.gsub(/[$^]/, '')
- {:name => route.name.to_s, :verb => verb, :path => route.path.spec.to_s, :reqs => reqs}
+ collect_engine_routes(reqs, rack_app)
+
+ {:name => route.name.to_s, :verb => verb, :path => route.path.spec.to_s, :reqs => reqs }
end
# Skip the route if it's internal info route
- routes.reject! { |r| r[:path] =~ %r{/rails/info/properties|^/assets} }
+ routes.reject { |r| r[:path] =~ %r{/rails/info/properties|^/assets} }
+ end
+
+ def collect_engine_routes(name, rack_app)
+ return unless rack_app && rack_app.respond_to?(:routes)
+ return if @engines[name]
+
+ routes = rack_app.routes
+ if routes.is_a?(ActionDispatch::Routing::RouteSet)
+ @engines[name] = collect_routes(routes.routes)
+ end
+ end
+
+ def formatted_routes_for_engines
+ @engines.map do |name, routes|
+ ["\nRoutes for #{name}:"] + formatted_routes(routes)
+ end.flatten
+ end
+ def formatted_routes(routes)
name_width = routes.map{ |r| r[:name].length }.max
verb_width = routes.map{ |r| r[:verb].length }.max
path_width = routes.map{ |r| r[:path].length }.max
diff --git a/railties/lib/rails/code_statistics.rb b/railties/lib/rails/code_statistics.rb
index e6822b75b7..435ea83ad8 100644
--- a/railties/lib/rails/code_statistics.rb
+++ b/railties/lib/rails/code_statistics.rb
@@ -38,11 +38,22 @@ class CodeStatistics #:nodoc:
next unless file_name =~ pattern
f = File.open(directory + "/" + file_name)
-
+ comment_started = false
while line = f.gets
stats["lines"] += 1
- stats["classes"] += 1 if line =~ /class [A-Z]/
- stats["methods"] += 1 if line =~ /def [a-z]/
+ if(comment_started)
+ if line =~ /^=end/
+ comment_started = false
+ end
+ next
+ else
+ if line =~ /^=begin/
+ comment_started = true
+ next
+ end
+ end
+ stats["classes"] += 1 if line =~ /^\s*class\s+[_A-Z]/
+ stats["methods"] += 1 if line =~ /^\s*def\s+[_a-z]/
stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
end
end
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb
index b0ba76217a..4b0acc9d88 100644
--- a/railties/lib/rails/commands/dbconsole.rb
+++ b/railties/lib/rails/commands/dbconsole.rb
@@ -33,7 +33,7 @@ module Rails
options['mode'] = mode
end
- opt.on("-h", "--header") do |h|
+ opt.on("--header") do |h|
options['header'] = h
end
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
index 4df849447d..c99a2e6685 100644
--- a/railties/lib/rails/commands/plugin.rb
+++ b/railties/lib/rails/commands/plugin.rb
@@ -274,198 +274,200 @@ end
# load default environment and parse arguments
require 'optparse'
-module Commands
- class Plugin
- attr_reader :environment, :script_name
- def initialize
- @environment = RailsEnvironment.default
- @rails_root = RailsEnvironment.default.root
- @script_name = File.basename($0)
- end
+module Rails
+ module Commands
+ class Plugin
+ attr_reader :environment, :script_name
+ def initialize
+ @environment = RailsEnvironment.default
+ @rails_root = RailsEnvironment.default.root
+ @script_name = File.basename($0)
+ end
- def environment=(value)
- @environment = value
- RailsEnvironment.default = value
- end
+ def environment=(value)
+ @environment = value
+ RailsEnvironment.default = value
+ end
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: plugin [OPTIONS] command"
- o.define_head "Rails plugin manager."
+ def options
+ OptionParser.new do |o|
+ o.set_summary_indent(' ')
+ o.banner = "Usage: plugin [OPTIONS] command"
+ o.define_head "Rails plugin manager."
- o.separator ""
- o.separator "GENERAL OPTIONS"
+ o.separator ""
+ o.separator "GENERAL OPTIONS"
- o.on("-r", "--root=DIR", String,
- "Set an explicit rails app directory.",
- "Default: #{@rails_root}") { |rails_root| @rails_root = rails_root; self.environment = RailsEnvironment.new(@rails_root) }
+ o.on("-r", "--root=DIR", String,
+ "Set an explicit rails app directory.",
+ "Default: #{@rails_root}") { |rails_root| @rails_root = rails_root; self.environment = RailsEnvironment.new(@rails_root) }
- o.on("-v", "--verbose", "Turn on verbose output.") { |verbose| $verbose = verbose }
- o.on("-h", "--help", "Show this help message.") { puts o; exit }
+ o.on("-v", "--verbose", "Turn on verbose output.") { |verbose| $verbose = verbose }
+ o.on("-h", "--help", "Show this help message.") { puts o; exit }
- o.separator ""
- o.separator "COMMANDS"
+ o.separator ""
+ o.separator "COMMANDS"
- o.separator " install Install plugin(s) from known repositories or URLs."
- o.separator " remove Uninstall plugins."
+ o.separator " install Install plugin(s) from known repositories or URLs."
+ o.separator " remove Uninstall plugins."
- o.separator ""
- o.separator "EXAMPLES"
- o.separator " Install a plugin from a subversion URL:"
- o.separator " #{@script_name} plugin install http://example.com/my_svn_plugin\n"
- o.separator " Install a plugin from a git URL:"
- o.separator " #{@script_name} plugin install git://github.com/SomeGuy/my_awesome_plugin.git\n"
- o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
- o.separator " #{@script_name} plugin install -x my_svn_plugin\n"
+ o.separator ""
+ o.separator "EXAMPLES"
+ o.separator " Install a plugin from a subversion URL:"
+ o.separator " #{@script_name} plugin install http://example.com/my_svn_plugin\n"
+ o.separator " Install a plugin from a git URL:"
+ o.separator " #{@script_name} plugin install git://github.com/SomeGuy/my_awesome_plugin.git\n"
+ o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
+ o.separator " #{@script_name} plugin install -x my_svn_plugin\n"
+ end
end
- end
- def parse!(args=ARGV)
- general, sub = split_args(args)
- options.parse!(general)
+ def parse!(args=ARGV)
+ general, sub = split_args(args)
+ options.parse!(general)
- command = general.shift
- if command =~ /^(install|remove)$/
- command = Commands.const_get(command.capitalize).new(self)
- command.parse!(sub)
- else
- puts "Unknown command: #{command}" unless command.blank?
- puts options
- exit 1
+ command = general.shift
+ if command =~ /^(install|remove)$/
+ command = Commands.const_get(command.capitalize).new(self)
+ command.parse!(sub)
+ else
+ puts "Unknown command: #{command}" unless command.blank?
+ puts options
+ exit 1
+ end
end
- end
- def split_args(args)
- left = []
- left << args.shift while args[0] and args[0] =~ /^-/
- left << args.shift if args[0]
- [left, args]
- end
-
- def self.parse!(args=ARGV)
- Plugin.new.parse!(args)
- end
- end
+ def split_args(args)
+ left = []
+ left << args.shift while args[0] and args[0] =~ /^-/
+ left << args.shift if args[0]
+ [left, args]
+ end
- class Install
- def initialize(base_command)
- @base_command = base_command
- @method = :http
- @options = { :quiet => false, :revision => nil, :force => false }
+ def self.parse!(args=ARGV)
+ Plugin.new.parse!(args)
+ end
end
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} install PLUGIN [PLUGIN [PLUGIN] ...]"
- o.define_head "Install one or more plugins."
- o.separator ""
- o.separator "Options:"
- o.on( "-x", "--externals",
- "Use svn:externals to grab the plugin.",
- "Enables plugin updates and plugin versioning.") { |v| @method = :externals }
- o.on( "-o", "--checkout",
- "Use svn checkout to grab the plugin.",
- "Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
- o.on( "-e", "--export",
- "Use svn export to grab the plugin.",
- "Exports the plugin, allowing you to check it into your local repository. Does not enable updates or add an svn:externals entry.") { |v| @method = :export }
- o.on( "-q", "--quiet",
- "Suppresses the output from installation.",
- "Ignored if -v is passed (rails plugin -v install ...)") { |v| @options[:quiet] = true }
- o.on( "-r REVISION", "--revision REVISION",
- "Checks out the given revision from subversion or git.",
- "Ignored if subversion/git is not used.") { |v| @options[:revision] = v }
- o.on( "-f", "--force",
- "Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
- o.separator ""
- o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
- o.separator "a plugin repository."
+ class Install
+ def initialize(base_command)
+ @base_command = base_command
+ @method = :http
+ @options = { :quiet => false, :revision => nil, :force => false }
end
- end
- def determine_install_method
- best = @base_command.environment.best_install_method
- @method = :http if best == :http and @method == :export
- case
- when (best == :http and @method != :http)
- msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
- when (best == :export and (@method != :export and @method != :http))
- msg = "Cannot install using #{@method} because this project is not under subversion."
- when (best != :externals and @method == :externals)
- msg = "Cannot install using externals because vendor/plugins is not under subversion."
+ def options
+ OptionParser.new do |o|
+ o.set_summary_indent(' ')
+ o.banner = "Usage: #{@base_command.script_name} install PLUGIN [PLUGIN [PLUGIN] ...]"
+ o.define_head "Install one or more plugins."
+ o.separator ""
+ o.separator "Options:"
+ o.on( "-x", "--externals",
+ "Use svn:externals to grab the plugin.",
+ "Enables plugin updates and plugin versioning.") { |v| @method = :externals }
+ o.on( "-o", "--checkout",
+ "Use svn checkout to grab the plugin.",
+ "Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
+ o.on( "-e", "--export",
+ "Use svn export to grab the plugin.",
+ "Exports the plugin, allowing you to check it into your local repository. Does not enable updates or add an svn:externals entry.") { |v| @method = :export }
+ o.on( "-q", "--quiet",
+ "Suppresses the output from installation.",
+ "Ignored if -v is passed (rails plugin -v install ...)") { |v| @options[:quiet] = true }
+ o.on( "-r REVISION", "--revision REVISION",
+ "Checks out the given revision from subversion or git.",
+ "Ignored if subversion/git is not used.") { |v| @options[:revision] = v }
+ o.on( "-f", "--force",
+ "Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
+ o.separator ""
+ o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
+ o.separator "a plugin repository."
+ end
end
- if msg
- puts msg
- exit 1
+
+ def determine_install_method
+ best = @base_command.environment.best_install_method
+ @method = :http if best == :http and @method == :export
+ case
+ when (best == :http and @method != :http)
+ msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
+ when (best == :export and (@method != :export and @method != :http))
+ msg = "Cannot install using #{@method} because this project is not under subversion."
+ when (best != :externals and @method == :externals)
+ msg = "Cannot install using externals because vendor/plugins is not under subversion."
+ end
+ if msg
+ puts msg
+ exit 1
+ end
+ @method
end
- @method
- end
- def parse!(args)
- options.parse!(args)
- if args.blank?
- puts options
+ def parse!(args)
+ options.parse!(args)
+ if args.blank?
+ puts options
+ exit 1
+ end
+ environment = @base_command.environment
+ install_method = determine_install_method
+ puts "Plugins will be installed using #{install_method}" if $verbose
+ args.each do |name|
+ ::Plugin.find(name).install(install_method, @options)
+ end
+ rescue StandardError => e
+ puts "Plugin not found: #{args.inspect}"
+ puts e.inspect if $verbose
exit 1
end
- environment = @base_command.environment
- install_method = determine_install_method
- puts "Plugins will be installed using #{install_method}" if $verbose
- args.each do |name|
- ::Plugin.find(name).install(install_method, @options)
- end
- rescue StandardError => e
- puts "Plugin not found: #{args.inspect}"
- puts e.inspect if $verbose
- exit 1
- end
- end
-
- class Remove
- def initialize(base_command)
- @base_command = base_command
end
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} remove name [name]..."
- o.define_head "Remove plugins."
+ class Remove
+ def initialize(base_command)
+ @base_command = base_command
end
- end
- def parse!(args)
- options.parse!(args)
- if args.blank?
- puts options
- exit 1
+ def options
+ OptionParser.new do |o|
+ o.set_summary_indent(' ')
+ o.banner = "Usage: #{@base_command.script_name} remove name [name]..."
+ o.define_head "Remove plugins."
+ end
end
- root = @base_command.environment.root
- args.each do |name|
- ::Plugin.new(name).uninstall
+
+ def parse!(args)
+ options.parse!(args)
+ if args.blank?
+ puts options
+ exit 1
+ end
+ root = @base_command.environment.root
+ args.each do |name|
+ ::Plugin.new(name).uninstall
+ end
end
end
- end
- class Info
- def initialize(base_command)
- @base_command = base_command
- end
+ class Info
+ def initialize(base_command)
+ @base_command = base_command
+ end
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} info name [name]..."
- o.define_head "Shows plugin info at {url}/about.yml."
+ def options
+ OptionParser.new do |o|
+ o.set_summary_indent(' ')
+ o.banner = "Usage: #{@base_command.script_name} info name [name]..."
+ o.define_head "Shows plugin info at {url}/about.yml."
+ end
end
- end
- def parse!(args)
- options.parse!(args)
- args.each do |name|
- puts ::Plugin.find(name).info
- puts
+ def parse!(args)
+ options.parse!(args)
+ args.each do |name|
+ puts ::Plugin.find(name).info
+ puts
+ end
end
end
end
@@ -539,4 +541,4 @@ class RecursiveHTTPFetcher
end
end
-Commands::Plugin.parse!
+Rails::Commands::Plugin.parse!
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index d652c6b7fe..5c1af99fe2 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -330,6 +330,17 @@ module Rails
#
# MyEngine::Engine.load_seed
#
+ # == Loading priority
+ #
+ # In order to change engine's priority you can use config.railties_order in main application.
+ # It will affect the priority of loading views, helpers, assets and all the other files
+ # related to engine or application.
+ #
+ # Example:
+ #
+ # # load Blog::Engine with highest priority, followed by application and other railties
+ # config.railties_order = [Blog::Engine, :main_app, :all]
+ #
class Engine < Railtie
autoload :Configuration, "rails/engine/configuration"
autoload :Railties, "rails/engine/railties"
@@ -371,20 +382,28 @@ module Rails
self.routes.default_scope = { :module => ActiveSupport::Inflector.underscore(mod.name) }
self.isolated = true
- unless mod.respond_to?(:_railtie)
- name = engine_name
- _railtie = self
+ unless mod.respond_to?(:railtie_namespace)
+ name, railtie = engine_name, self
+
mod.singleton_class.instance_eval do
- define_method(:_railtie) do
- _railtie
- end
+ define_method(:railtie_namespace) { railtie }
unless mod.respond_to?(:table_name_prefix)
- define_method(:table_name_prefix) do
- "#{name}_"
- end
+ define_method(:table_name_prefix) { "#{name}_" }
end
- end
+
+ unless mod.respond_to?(:use_relative_model_naming?)
+ class_eval "def use_relative_model_naming?; true; end", __FILE__, __LINE__
+ end
+
+ unless mod.respond_to?(:railtie_helpers_paths)
+ define_method(:railtie_helpers_paths) { railtie.helpers_paths }
+ end
+
+ unless mod.respond_to?(:railtie_routes_url_helpers)
+ define_method(:railtie_routes_url_helpers) { railtie.routes_url_helpers }
+ end
+ end
end
end
@@ -429,13 +448,6 @@ module Rails
def helpers
@helpers ||= begin
helpers = Module.new
-
- helpers_paths = if config.respond_to?(:helpers_paths)
- config.helpers_paths
- else
- paths["app/helpers"].existent
- end
-
all = ActionController::Base.all_helpers_from_path(helpers_paths)
ActionController::Base.modules_for_helpers(all).each do |mod|
helpers.send(:include, mod)
@@ -444,6 +456,14 @@ module Rails
end
end
+ def helpers_paths
+ paths["app/helpers"].existent
+ end
+
+ def routes_url_helpers
+ routes.url_helpers
+ end
+
def app
@app ||= begin
config.middleware = config.middleware.merge_into(default_middleware_stack)
@@ -471,10 +491,19 @@ module Rails
@routes
end
+ def ordered_railties
+ railties.all + [self]
+ end
+
def initializers
initializers = []
- railties.all { |r| initializers += r.initializers }
- initializers += super
+ ordered_railties.each do |r|
+ if r == self
+ initializers += super
+ else
+ initializers += r.initializers
+ end
+ end
initializers
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index b26839644e..ca93f9ef9d 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -68,8 +68,9 @@ module Rails
end
in_root do
- str = "gem #{parts.join(", ")}\n"
+ str = "gem #{parts.join(", ")}"
str = " " + str if @in_group
+ str = "\n" + str
append_file "Gemfile", str, :verbose => false
end
end
@@ -87,13 +88,13 @@ module Rails
log :gemfile, "group #{name}"
in_root do
- append_file "Gemfile", "\ngroup #{name} do\n", :force => true
+ append_file "Gemfile", "\ngroup #{name} do", :force => true
@in_group = true
instance_eval(&block)
@in_group = false
- append_file "Gemfile", "end\n", :force => true
+ append_file "Gemfile", "\nend\n", :force => true
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 0a79d6e86e..3fbde0d989 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -199,6 +199,7 @@ module Rails
group :assets do
gem 'sass-rails', :git => 'git://github.com/rails/sass-rails.git'
gem 'coffee-rails', :git => 'git://github.com/rails/coffee-rails.git'
+ #{"gem 'therubyrhino'\n" if defined?(JRUBY_VERSION)}
gem 'uglifier', '>= 1.0.3'
end
GEMFILE
diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
index c63d1b6ac5..bba96a7431 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
@@ -2,7 +2,7 @@
<html>
<head>
<title><%= camelized %></title>
- <%%= stylesheet_link_tag "application" %>
+ <%%= stylesheet_link_tag "application", :media => "all" %>
<%%= javascript_include_tag "application" %>
<%%= csrf_meta_tags %>
</head>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index 13fbe9e526..40fd843b1b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -49,6 +49,11 @@ module <%= app_const_base %>
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
+ # Use SQL instead of Active Record's schema dumper when creating the database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
<% unless options.skip_sprockets? -%>
# Enable the asset pipeline
config.assets.enabled = true
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
index 80198cc21e..37a8b81dad 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
@@ -29,11 +29,6 @@
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
- # Use SQL instead of Active Record's schema dumper when creating the test database.
- # This is necessary if your schema can't be completely dumped by the schema dumper,
- # like if you have constraints or database-specific column types
- # config.active_record.schema_format = :sql
-
<%- unless options.skip_active_record? -%>
# Raise exception on mass assignment protection for ActiveRecord models
config.active_record.mass_assignment_sanitizer = :strict
diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
index f5c8ccf940..cd7d51e628 100644
--- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
@@ -246,8 +246,20 @@ task :default => :test
"rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]"
end
+ def original_name
+ @original_name ||= File.basename(destination_root)
+ end
+
def name
- @name ||= File.basename(destination_root)
+ @name ||= begin
+ # same as ActiveSupport::Inflector#underscore except not replacing '-'
+ underscored = original_name.dup
+ underscored.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
+ underscored.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
+ underscored.downcase!
+
+ underscored
+ end
end
def camelized
@@ -256,11 +268,11 @@ task :default => :test
def valid_const?
if camelized =~ /^\d/
- raise Error, "Invalid plugin name #{name}. Please give a name which does not start with numbers."
+ raise Error, "Invalid plugin name #{original_name}. Please give a name which does not start with numbers."
elsif RESERVED_NAMES.include?(name)
- raise Error, "Invalid plugin name #{name}. Please give a name which does not match one of the reserved rails words."
+ raise Error, "Invalid plugin name #{original_name}. Please give a name which does not match one of the reserved rails words."
elsif Object.const_defined?(camelized)
- raise Error, "Invalid plugin name #{name}, constant #{camelized} is already in use. Please choose another plugin name."
+ raise Error, "Invalid plugin name #{original_name}, constant #{camelized} is already in use. Please choose another plugin name."
end
end
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt
index 01550dec2f..bd983fb90f 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt
@@ -2,7 +2,7 @@
<html>
<head>
<title><%= camelized %></title>
- <%%= stylesheet_link_tag "<%= name %>/application" %>
+ <%%= stylesheet_link_tag "<%= name %>/application", :media => "all" %>
<%%= javascript_include_tag "<%= name %>/application" %>
<%%= csrf_meta_tags %>
</head>
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index e8fb1f3d98..f0991b99af 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -196,7 +196,7 @@ module Rails
end
def railtie_namespace
- @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:_railtie) }
+ @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) }
end
end
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index f356805d6e..f37a024a0b 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -524,6 +524,7 @@ module ApplicationTests
assert_equal app.env_config['action_dispatch.parameter_filter'], app.config.filter_parameters
assert_equal app.env_config['action_dispatch.secret_token'], app.config.secret_token
assert_equal app.env_config['action_dispatch.show_exceptions'], app.config.action_dispatch.show_exceptions
+ assert_equal app.env_config['action_dispatch.logger'], Rails.logger
end
end
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index b3745f194e..2073c780bf 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -71,7 +71,6 @@ class ConsoleTest < Test::Unit::TestCase
assert !User.new.respond_to?(:age)
silence_stream(STDOUT) { irb_context.reload! }
- session = irb_context.new_session
assert User.new.respond_to?(:age)
end
diff --git a/railties/test/application/middleware/cookies_test.rb b/railties/test/application/middleware/cookies_test.rb
new file mode 100644
index 0000000000..13556cbed2
--- /dev/null
+++ b/railties/test/application/middleware/cookies_test.rb
@@ -0,0 +1,47 @@
+require 'isolation/abstract_unit'
+
+module ApplicationTests
+ class CookiesTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def new_app
+ File.expand_path("#{app_path}/../new_app")
+ end
+
+ def setup
+ build_app
+ boot_rails
+ FileUtils.rm_rf("#{app_path}/config/environments")
+ end
+
+ def teardown
+ teardown_app
+ FileUtils.rm_rf(new_app) if File.directory?(new_app)
+ end
+
+ test 'always_write_cookie is true by default in development' do
+ require 'rails'
+ Rails.env = 'development'
+ require "#{app_path}/config/environment"
+ assert_equal true, ActionDispatch::Cookies::CookieJar.always_write_cookie
+ end
+
+ test 'always_write_cookie is false by default in production' do
+ require 'rails'
+ Rails.env = 'production'
+ require "#{app_path}/config/environment"
+ assert_equal false, ActionDispatch::Cookies::CookieJar.always_write_cookie
+ end
+
+ test 'always_write_cookie can be overrided' do
+ add_to_config <<-RUBY
+ config.action_dispatch.always_write_cookie = false
+ RUBY
+
+ require 'rails'
+ Rails.env = 'development'
+ require "#{app_path}/config/environment"
+ assert_equal false, ActionDispatch::Cookies::CookieJar.always_write_cookie
+ end
+ end
+end
diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb
index ff9cdcadc7..86e1995def 100644
--- a/railties/test/application/rackup_test.rb
+++ b/railties/test/application/rackup_test.rb
@@ -6,7 +6,7 @@ module ApplicationTests
def rackup
require "rack"
- app, options = Rack::Builder.parse_file("#{app_path}/config.ru")
+ app, _ = Rack::Builder.parse_file("#{app_path}/config.ru")
app
end
diff --git a/railties/test/application/route_inspect_test.rb b/railties/test/application/route_inspect_test.rb
index 78980705ed..2ad5ee6c4c 100644
--- a/railties/test/application/route_inspect_test.rb
+++ b/railties/test/application/route_inspect_test.rb
@@ -1,6 +1,7 @@
require 'test/unit'
require 'rails/application/route_inspector'
require 'action_controller'
+require 'rails/engine'
module ApplicationTests
class RouteInspectTest < Test::Unit::TestCase
@@ -9,6 +10,31 @@ module ApplicationTests
@inspector = Rails::Application::RouteInspector.new
end
+ def test_displaying_routes_for_engines
+ engine = Class.new(Rails::Engine) do
+ def self.to_s
+ "Blog::Engine"
+ end
+ end
+ engine.routes.draw do
+ get '/cart', :to => 'cart#show'
+ end
+
+ @set.draw do
+ get '/custom/assets', :to => 'custom_assets#show'
+ mount engine => "/blog", :as => "blog"
+ end
+
+ output = @inspector.format @set.routes
+ expected = [
+ "custom_assets GET /custom/assets(.:format) custom_assets#show",
+ " blog /blog Blog::Engine",
+ "\nRoutes for Blog::Engine:",
+ "cart GET /cart(.:format) cart#show"
+ ]
+ assert_equal expected, output
+ end
+
def test_cart_inspect
@set.draw do
get '/cart', :to => 'cart#show'
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index 51fa2fe16f..c1fd6a38f1 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -95,11 +95,13 @@ class ActionsTest < Rails::Generators::TestCase
def test_gem_should_insert_on_separate_lines
run_generator
+ File.open('Gemfile', 'a') {|f| f.write('# Some content...') }
+
action :gem, 'rspec'
action :gem, 'rspec-rails'
- assert_file 'Gemfile', /gem "rspec"$/
- assert_file 'Gemfile', /gem "rspec-rails"$/
+ assert_file 'Gemfile', /^gem "rspec"$/
+ assert_file 'Gemfile', /^gem "rspec-rails"$/
end
def test_gem_group_should_wrap_gems_in_a_group
@@ -112,7 +114,7 @@ class ActionsTest < Rails::Generators::TestCase
action :gem_group, :test do
gem 'fakeweb'
end
-
+
assert_file 'Gemfile', /\ngroup :development, :test do\n gem "rspec-rails"\nend\n\ngroup :test do\n gem "fakeweb"\nend/
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 955ed09361..a1bd2fbaa5 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -208,6 +208,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "test/performance/browsing_test.rb"
end
+ def test_inclusion_of_therubyrhino_under_jruby
+ if defined?(JRUBY_VERSION)
+ run_generator([destination_root])
+ assert_file "Gemfile", /gem\s+["']therubyrhino["']$/
+ end
+ end
+
def test_creation_of_a_test_directory
run_generator
assert_file 'test'
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index b70f9f4d9c..826eac904e 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -37,6 +37,12 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "things-43/lib/things-43.rb", /module Things43/
end
+ def test_camelcase_plugin_name_underscores_filenames
+ run_generator [File.join(destination_root, "CamelCasedName")]
+ assert_no_file "CamelCasedName/lib/CamelCasedName.rb"
+ assert_file "CamelCasedName/lib/camel_cased_name.rb", /module CamelCasedName/
+ end
+
def test_generating_without_options
run_generator
assert_file "README.rdoc", /Bukkits/
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 22dbcf9644..400cae98b2 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -323,7 +323,7 @@ module RailtiesTest
assert_equal "bukkits_", Bukkits.table_name_prefix
assert_equal "bukkits", Bukkits::Engine.engine_name
- assert_equal Bukkits._railtie, Bukkits::Engine
+ assert_equal Bukkits.railtie_namespace, Bukkits::Engine
assert ::Bukkits::MyMailer.method_defined?(:foo_path)
assert !::Bukkits::MyMailer.method_defined?(:bar_path)
@@ -467,7 +467,7 @@ module RailtiesTest
assert_nil Rails.application.load_seed
end
- test "using namespace more than once on one module should not overwrite _railtie method" do
+ test "using namespace more than once on one module should not overwrite railtie_namespace method" do
@plugin.write "lib/bukkits.rb", <<-RUBY
module AppTemplate
class Engine < ::Rails::Engine
@@ -484,7 +484,7 @@ module RailtiesTest
boot_rails
- assert_equal AppTemplate._railtie, AppTemplate::Engine
+ assert_equal AppTemplate.railtie_namespace, AppTemplate::Engine
end
test "properly reload routes" do
@@ -667,6 +667,132 @@ module RailtiesTest
assert_equal expected, methods
end
+ test "setting priority for engines with config.railties_order" do
+ @blog = engine "blog" do |plugin|
+ plugin.write "lib/blog.rb", <<-RUBY
+ module Blog
+ class Engine < ::Rails::Engine
+ end
+ end
+ RUBY
+ end
+
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ isolate_namespace Bukkits
+ end
+ end
+ RUBY
+
+ controller "main", <<-RUBY
+ class MainController < ActionController::Base
+ def foo
+ render :inline => '<%= render :partial => "shared/foo" %>'
+ end
+
+ def bar
+ render :inline => '<%= render :partial => "shared/bar" %>'
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ match "/foo" => "main#foo"
+ match "/bar" => "main#bar"
+ end
+ RUBY
+
+ @plugin.write "app/views/shared/_foo.html.erb", <<-RUBY
+ Bukkit's foo partial
+ RUBY
+
+ app_file "app/views/shared/_foo.html.erb", <<-RUBY
+ App's foo partial
+ RUBY
+
+ @blog.write "app/views/shared/_bar.html.erb", <<-RUBY
+ Blog's bar partial
+ RUBY
+
+ app_file "app/views/shared/_bar.html.erb", <<-RUBY
+ App's bar partial
+ RUBY
+
+ @plugin.write "app/assets/javascripts/foo.js", <<-RUBY
+ // Bukkit's foo js
+ RUBY
+
+ app_file "app/assets/javascripts/foo.js", <<-RUBY
+ // App's foo js
+ RUBY
+
+ @blog.write "app/assets/javascripts/bar.js", <<-RUBY
+ // Blog's bar js
+ RUBY
+
+ app_file "app/assets/javascripts/bar.js", <<-RUBY
+ // App's bar js
+ RUBY
+
+ add_to_config("config.railties_order = [:all, :main_app, Blog::Engine]")
+
+ boot_rails
+ require "#{rails_root}/config/environment"
+
+ get("/foo")
+ assert_equal "Bukkit's foo partial", last_response.body.strip
+
+ get("/bar")
+ assert_equal "App's bar partial", last_response.body.strip
+
+ get("/assets/foo.js")
+ assert_equal "// Bukkit's foo js\n;", last_response.body.strip
+
+ get("/assets/bar.js")
+ assert_equal "// App's bar js\n;", last_response.body.strip
+ end
+
+ test "railties_order adds :all with lowest priority if not given" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ end
+ end
+ RUBY
+
+ controller "main", <<-RUBY
+ class MainController < ActionController::Base
+ def foo
+ render :inline => '<%= render :partial => "shared/foo" %>'
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ match "/foo" => "main#foo"
+ end
+ RUBY
+
+ @plugin.write "app/views/shared/_foo.html.erb", <<-RUBY
+ Bukkit's foo partial
+ RUBY
+
+ app_file "app/views/shared/_foo.html.erb", <<-RUBY
+ App's foo partial
+ RUBY
+
+ add_to_config("config.railties_order = [Bukkits::Engine]")
+
+ boot_rails
+ require "#{rails_root}/config/environment"
+
+ get("/foo")
+ assert_equal "Bukkit's foo partial", last_response.body.strip
+ end
+
private
def app
Rails.application