Merge branch 'master' of git://github.com/rails/rails

This commit is contained in:
Rizwan Reza
2010-06-05 04:04:49 +04:30
38 changed files with 172 additions and 63 deletions

View File

@@ -311,6 +311,7 @@ module ActionMailer #:nodoc:
include AbstractController::Layouts
include AbstractController::Helpers
include AbstractController::Translation
include AbstractController::AssetPaths
helper ActionMailer::MailHelper

View File

@@ -13,7 +13,16 @@ module ActionMailer
end
initializer "action_mailer.set_configs" do |app|
paths = app.config.paths
am = app.config.action_mailer
am.assets_dir ||= paths.public.to_a.first
am.javascripts_dir ||= paths.public.javascripts.to_a.first
am.stylesheets_dir ||= paths.public.stylesheets.to_a.first
ActiveSupport.on_load(:action_mailer) do
self.config.merge!(am)
include app.routes.url_helpers
app.config.action_mailer.each do |k,v|

View File

@@ -1,5 +1,7 @@
*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
* Remove middleware laziness [José Valim]
* Make session stores rely on request.cookie_jar and change set_session semantics to return the cookie value instead of a boolean. [José Valim]
* OAuth 2: HTTP Token Authorization support to complement Basic and Digest Authorization. [Rick Olson]

View File

@@ -20,5 +20,6 @@ module AbstractController
autoload :Logger
autoload :Rendering
autoload :Translation
autoload :AssetPaths
autoload :ViewPaths
end

View File

@@ -0,0 +1,9 @@
module AbstractController
module AssetPaths
extend ActiveSupport::Concern
included do
config_accessor :assets_dir, :javascripts_dir, :stylesheets_dir
end
end
end

View File

@@ -1,4 +1,5 @@
require 'active_support/configurable'
require 'active_support/core_ext/module/anonymous'
module AbstractController
class Error < StandardError; end

View File

@@ -1,4 +1,5 @@
require "abstract_controller/base"
require "action_view"
module AbstractController
class DoubleRenderError < Error

View File

@@ -13,6 +13,7 @@ module ActionController
MODULES = [
AbstractController::Layouts,
AbstractController::Translation,
AbstractController::AssetPaths,
Helpers,
HideActions,
@@ -66,8 +67,7 @@ module ActionController
@subclasses ||= []
end
# TODO Move this to the appropriate module
config_accessor :assets_dir, :asset_path, :javascripts_dir, :stylesheets_dir
config_accessor :asset_host, :asset_path
ActiveSupport.run_load_hooks(:action_controller, self)
end

View File

@@ -8,10 +8,10 @@ module ActionController
delegate :headers, :status=, :location=, :content_type=,
:status, :location, :content_type, :to => "@_response"
def dispatch(action, request)
@_response = ActionDispatch::Response.new
@_response.request = request
super
def dispatch(action, request, response = ActionDispatch::Response.new)
@_response ||= response
@_response.request ||= request
super(action, request)
end
def params

View File

@@ -47,6 +47,7 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
include AbstractController::Helpers
include AbstractController::Callbacks
included do
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+

View File

@@ -31,6 +31,7 @@ module ActionView #:nodoc:
def typecast!
each_with_index do |path, i|
path = path.to_s if path.is_a?(Pathname)
next unless path.is_a?(String)
self[i] = FileSystemResolver.new(path)
end

View File

@@ -411,7 +411,8 @@ module ActiveRecord
end
elsif @reflection.klass.scopes[method]
@_named_scopes_cache ||= {}
@_named_scopes_cache[method] ||= with_scope(construct_scope) { @reflection.klass.send(method, *args) }
@_named_scopes_cache[method] ||= {}
@_named_scopes_cache[method][args] ||= with_scope(construct_scope) { @reflection.klass.send(method, *args) }
else
with_scope(construct_scope) do
if block_given?

View File

@@ -435,6 +435,7 @@ namespace :db do
task :create => :environment do
raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
require 'rails/generators'
Rails::Generators.configure!
require 'rails/generators/rails/session_migration/session_migration_generator'
Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ]
end

View File

@@ -9,7 +9,7 @@ module ActiveRecord
(ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS).each do |query_method|
attr_accessor :"#{query_method}_values"
next if [:where, :having].include?(query_method)
next if [:where, :having, :select].include?(query_method)
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
def #{query_method}(*args, &block)
new_relation = clone
@@ -21,6 +21,19 @@ module ActiveRecord
CEVAL
end
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
def select(*args, &block)
if block_given?
to_a.select(&block)
else
new_relation = clone
value = Array.wrap(args.flatten).reject {|x| x.blank? }
new_relation.select_values += value if value.present?
new_relation
end
end
CEVAL
[:where, :having].each do |query_method|
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
def #{query_method}(*args, &block)

View File

@@ -17,7 +17,7 @@ module Remembered
module ClassMethods
def remembered; @@remembered ||= []; end
def random_element; @@remembered.random_element; end
def sample; @@remembered.sample; end
end
end
@@ -79,14 +79,14 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase
[Circle, Square, Triangle, NonPolyOne, NonPolyTwo].map(&:create!)
end
1.upto(NUM_SIMPLE_OBJS) do
PaintColor.create!(:non_poly_one_id => NonPolyOne.random_element.id)
PaintTexture.create!(:non_poly_two_id => NonPolyTwo.random_element.id)
PaintColor.create!(:non_poly_one_id => NonPolyOne.sample.id)
PaintTexture.create!(:non_poly_two_id => NonPolyTwo.sample.id)
end
1.upto(NUM_SHAPE_EXPRESSIONS) do
shape_type = [Circle, Square, Triangle].random_element
paint_type = [PaintColor, PaintTexture].random_element
ShapeExpression.create!(:shape_type => shape_type.to_s, :shape_id => shape_type.random_element.id,
:paint_type => paint_type.to_s, :paint_id => paint_type.random_element.id)
shape_type = [Circle, Square, Triangle].sample
paint_type = [PaintColor, PaintTexture].sample
ShapeExpression.create!(:shape_type => shape_type.to_s, :shape_id => shape_type.sample.id,
:paint_type => paint_type.to_s, :paint_id => paint_type.sample.id)
end
end

View File

@@ -301,7 +301,7 @@ class NamedScopeTest < ActiveRecord::TestCase
end
def test_rand_should_select_a_random_object_from_proxy
assert_kind_of Topic, Topic.approved.random_element
assert_kind_of Topic, Topic.approved.sample
end
def test_should_use_where_in_query_for_named_scope
@@ -428,6 +428,19 @@ class NamedScopeTest < ActiveRecord::TestCase
assert_no_queries { post.comments.containing_the_letter_e.all }
end
def test_named_scopes_with_arguments_are_cached_on_associations
post = posts(:welcome)
one = post.comments.limit_by(1).all
assert_equal 1, one.size
two = post.comments.limit_by(2).all
assert_equal 2, two.size
assert_no_queries { post.comments.limit_by(1).all }
assert_no_queries { post.comments.limit_by(2).all }
end
def test_named_scopes_are_reset_on_association_reload
post = posts(:welcome)

View File

@@ -112,6 +112,11 @@ class RelationTest < ActiveRecord::TestCase
assert_equal 4, developers.map(&:salary).uniq.size
end
def test_select_with_block
even_ids = Developer.scoped.select {|d| d.id % 2 == 0 }.map(&:id)
assert_equal [2, 4, 6, 8, 10], even_ids
end
def test_finding_with_hash_conditions_on_joined_table
firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
assert_equal 1, firms.size

View File

@@ -1,4 +1,5 @@
class Comment < ActiveRecord::Base
scope :limit_by, lambda {|l| limit(l) }
scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'"
scope :for_first_post, :conditions => { :post_id => 1 }
scope :for_first_author,

View File

@@ -4,7 +4,7 @@
* Ruby 1.9: support UTF-8 case folding. #4595 [Norman Clarke]
* Renames Array#rand -> Array#random_element. [Santiago Pastorino, Rizwan Reza]
* Removes Array#rand and backports Array#sample from Ruby 1.9, thanks to Marc-Andre Lafortune. [fxn]
* Ruby 1.9: Renames last_(month|year) to prev_(month|year) in Date and Time. [fxn]

View File

@@ -1,6 +1,20 @@
class Array
# Returns a random element from the array.
def random_element
self[Kernel.rand(length)]
end
# Backport of Array#sample based on Marc-Andre Lafortune's http://github.com/marcandre/backports/
def sample(n=nil)
return self[Kernel.rand(size)] if n.nil?
n = n.to_int
rescue Exception => e
raise TypeError, "Coercion error: #{n.inspect}.to_int => Integer failed:\n(#{e.message})"
else
raise TypeError, "Coercion error: obj.to_int did NOT return an Integer (was #{n.class})" unless n.kind_of? Integer
raise ArgumentError, "negative array size" if n < 0
n = size if n > size
result = Array.new(self)
n.times do |i|
r = i + Kernel.rand(size - i)
result[i], result[r] = result[r], result[i]
end
result[n..size] = []
result
end unless method_defined? :sample
end

View File

@@ -2,7 +2,7 @@ module Kernel
unless respond_to?(:debugger)
# Starts a debugging session if ruby-debug has been loaded (call rails server --debugger to do load it).
def debugger
message = "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n"
message = "\n***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****\n"
defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
end
end

View File

@@ -359,14 +359,30 @@ class ArrayUniqByTests < Test::Unit::TestCase
end
class ArrayExtRandomTests < ActiveSupport::TestCase
def test_random_element_from_array
assert_nil [].random_element
def test_sample_from_array
assert_nil [].sample
assert_equal [], [].sample(5)
assert_equal 42, [42].sample
assert_equal [42], [42].sample(5)
Kernel.expects(:rand).with(1).returns(0)
assert_equal 'x', ['x'].random_element
a = [:foo, :bar, 42]
s = a.sample(2)
assert_equal 2, s.size
assert_equal 1, (a-s).size
assert_equal [], a-(0..20).sum{a.sample(2)}
o = Object.new
def o.to_int; 1; end
assert_equal [0], [0].sample(o)
o = Object.new
assert_raises(TypeError) { [0].sample(o) }
o = Object.new
def o.to_int; ''; end
assert_raises(TypeError) { [0].sample(o) }
Kernel.expects(:rand).with(3).returns(1)
assert_equal 2, [1, 2, 3].random_element
assert_raises(ArgumentError) { [0].sample(-7) }
end
end

View File

@@ -1,7 +1,7 @@
*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
* Version bump
* Removed Rails Metal [YK & JV].
*Rails 3.0.0 [beta 3] (April 13th, 2010)*

View File

@@ -81,7 +81,7 @@ The new installing rails sequence (for the beta) is:
<shell>
$ gem install rails --prerelease
$ rails myapp
$ rails new myapp
$ cd myapp
</shell>
@@ -98,13 +98,13 @@ h4. Living on the Edge
If you want to bundle straight from the Git repository, you can pass the +--edge+ flag:
<shell>
$ rails myapp --edge
$ rails new myapp --edge
</shell>
If you have a local checkout of the Rails repository and want to generate an application using that, you can pass the +--dev+ flag:
<shell>
$ ruby /path/to/rails/bin/rails myapp --dev
$ ruby /path/to/rails/bin/rails new myapp --dev
</shell>
h3. Rails Architectural Changes
@@ -512,6 +512,7 @@ These are the main changes in Active Support:
* Active Support no longer provides vendored versions of "TZInfo":http://tzinfo.rubyforge.org/, "Memcache Client":http://deveiate.org/projects/RMemCache/ and "Builder":http://builder.rubyforge.org/, these are all included as dependencies and installed via the <tt>bundle install</tt> command.
* Safe buffers are implemented in <tt>ActiveSupport::SafeBuffer</tt>.
* Added <tt>Array.uniq_by</tt> and <tt>Array.uniq_by!</tt>.
* Removed <tt>Array#rand</tt> and backported <tt>Array#sample</tt> from Ruby 1.9.
* Fixed bug on +TimeZone.seconds_to_utc_offset+ returning wrong value.
* Added <tt>ActiveSupport::Notifications</tt> middleware.
* <tt>ActiveSupport.use_standard_json_time_format</tt> now defaults to true.

View File

@@ -1927,13 +1927,21 @@ Similarly, +from+ returns the tail from the element at the passed index on:
The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is builtin). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available.
You can pick a random element with +random_element+:
NOTE: Defined in +active_support/core_ext/array/access.rb+.
h4. Random Access
Active Support backports +sample+ from Ruby 1.9:
<ruby>
shape_type = [Circle, Square, Triangle].random_element
shape_type = [Circle, Square, Triangle].sample
# => Square, for example
shape_types = [Circle, Square, Triangle].sample(2)
# => [Triangle, Circle], for example
</ruby>
NOTE: Defined in +active_support/core_ext/array/access.rb+.
NOTE: Defined in +active_support/core_ext/array/random_access.rb+.
h4. Options Extraction

View File

@@ -20,7 +20,7 @@ h3. First contact
When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +rails generate+:
<shell>
$ rails myapp
$ rails new myapp
$ cd myapp
$ rails generate
</shell>
@@ -322,16 +322,12 @@ config.generators do |g|
g.template_engine :erb
g.test_framework :shoulda, :fixture => false
g.stylesheets false
# Add a fallback!
g.fallbacks[:should] = :test_unit
end
</ruby>
And at the end of the same file:
<ruby>
require 'rails/generators'
Rails::Generators.fallbacks[:shoulda] = :test_unit
</ruby>
Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators:
<shell>
@@ -361,7 +357,7 @@ $ rails generate scaffold Comment body:text
create test/unit/helpers/comments_helper_test.rb
</shell>
Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of code duplication.
Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of duplication.
h3. Changelog

View File

@@ -160,7 +160,7 @@ The best way to use this guide is to follow each step as it happens, no code or
To begin, open a terminal, navigate to a folder where you have rights to create files, and type:
<shell>
$ rails blog
$ rails new blog
</shell>
This will create a Rails application called Blog in a directory called blog.

View File

@@ -14,13 +14,13 @@ h3. Usage
To apply a template, you need to provide the Rails generator with the location of the template you wish to apply, using -m option :
<shell>
$ rails blog -m ~/template.rb
$ rails new blog -m ~/template.rb
</shell>
It's also possible to apply a template using a URL :
<shell>
$ rails blog -m http://gist.github.com/31208.txt
$ rails new blog -m http://gist.github.com/31208.txt
</shell>
Alternatively, you can use the rake task +rails:template+ to apply a template to an existing Rails application :

View File

@@ -38,6 +38,10 @@ when 'dbconsole'
when 'application', 'runner'
require "rails/commands/#{command}"
when 'new'
puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n"
puts "Type 'rails' for help."
when '--version', '-v'
ARGV.unshift '--version'
require 'rails/commands/application'
@@ -53,6 +57,8 @@ The most common rails commands are:
server Start the Rails server (short-cut alias: "s")
dbconsole Start a console for the database specified in config/database.yml
(short-cut alias: "db")
new Create a new Rails application. "rails new my_app" creates a
new application called MyApp in "./my_app"
In addition to those, there are:
application Generate the Rails application code

View File

@@ -4,7 +4,12 @@ if %w(--version -v).include? ARGV.first
exit(0)
end
ARGV << "--help" if ARGV.empty?
if ARGV.first != "new" || ARGV.empty?
ARGV[0] = "--help"
else
ARGV.shift
end
require 'rubygems' if ARGV.include?("--dev")
require 'rails/generators'

View File

@@ -1,4 +1,5 @@
require 'rails/generators'
Rails::Generators.configure!
if [nil, "-h", "--help"].include?(ARGV.first)
Rails::Generators.help 'destroy'

View File

@@ -1,4 +1,5 @@
require 'rails/generators'
Rails::Generators.configure!
if [nil, "-h", "--help"].include?(ARGV.first)
Rails::Generators.help 'generate'

View File

@@ -68,6 +68,7 @@ module Rails
options.deep_merge! config.options
fallbacks.merge! config.fallbacks
templates_path.concat config.templates
templates_path.uniq!
end
def self.templates_path
@@ -328,10 +329,5 @@ module Rails
paths.uniq!
paths
end
end
end
# If the application was already defined, configure generators,
# otherwise you have to configure it by hand.
Rails::Generators.configure! if Rails.respond_to?(:application) && Rails.application
end

View File

@@ -1,9 +1,9 @@
Description:
The 'rails' command creates a new Rails application with a default
The 'rails new' command creates a new Rails application with a default
directory structure and configuration at the path you specify.
Example:
rails ~/Code/Ruby/weblog
rails new ~/Code/Ruby/weblog
This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
See the README in the newly created application to get going.

View File

@@ -149,8 +149,7 @@ module Rails
# can change in Ruby 1.8.7 when we FileUtils.cd.
RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__))
RESERVED_NAMES = %w[generate g console c server s dbconsole db
application destroy benchmarker profiler
RESERVED_NAMES = %w[application destroy benchmarker profiler
plugin runner test]
class AppGenerator < Base
@@ -310,7 +309,7 @@ module Rails
protected
def self.banner
"rails #{self.arguments.map(&:usage).join(' ')} [options]"
"rails new #{self.arguments.map(&:usage).join(' ')} [options]"
end
def builder

View File

@@ -23,6 +23,9 @@ gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= req
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug'
# Bundle the extra gems:
# gem 'bj'
# gem 'nokogiri', '1.4.1'

View File

@@ -47,7 +47,7 @@ module ApplicationTests
test "if there's no config.active_support.bare, all of ActiveSupport is required" do
use_frameworks []
require "#{app_path}/config/environment"
assert_nothing_raised { [1,2,3].random_element }
assert_nothing_raised { [1,2,3].sample }
end
test "config.active_support.bare does not require all of ActiveSupport" do
@@ -57,7 +57,7 @@ module ApplicationTests
Dir.chdir("#{app_path}/app") do
require "#{app_path}/config/environment"
assert_raises(NoMethodError) { [1,2,3].random_element }
assert_raises(NoMethodError) { [1,2,3].sample }
end
end

View File

@@ -1,4 +1,6 @@
require 'abstract_unit'
require 'rails/generators'
require 'rails/generators/test_case'
module Rails
def self.root
@@ -8,8 +10,9 @@ end
Rails.application.config.root = Rails.root
Rails.application.config.generators.templates = [File.join(Rails.root, "lib", "templates")]
require 'rails/generators'
require 'rails/generators/test_case'
# Call configure to load the settings from
# Rails.application.config.generators to Rails::Generators
Rails::Generators.configure!
require 'active_record'
require 'action_dispatch'