提交 942fe651 编写于 作者: D David Heinemeier Hansson

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

*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]
......
require 'active_support/configurable'
require 'active_support/core_ext/module/anonymous'
module AbstractController
class Error < StandardError; end
......
require "abstract_controller/base"
require "action_view"
module AbstractController
class DoubleRenderError < Error
......
......@@ -8,10 +8,10 @@ module RackDelegation
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
......
......@@ -47,6 +47,7 @@ module RequestForgeryProtection
extend ActiveSupport::Concern
include AbstractController::Helpers
include AbstractController::Callbacks
included do
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
......
......@@ -43,25 +43,25 @@ def safe_concat(string)
# ==== Examples
#
# truncate("Once upon a time in a world far far away")
# # => Once upon a time in a worl...
# # => "Once upon a time in a world..."
#
# truncate("Once upon a time in a world far far away", :separator => ' ')
# # => Once upon a time in a world...
# truncate("Once upon a time in a world far far away", :length => 17)
# # => "Once upon a ti..."
#
# truncate("Once upon a time in a world far far away", :length => 14)
# # => Once upon a...
# truncate("Once upon a time in a world far far away", :lenght => 17, :separator => ' ')
# # => "Once upon a..."
#
# truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 25)
# # => And they f... (continued)
# truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)')
# # => "And they f... (continued)"
#
# You can still use <tt>truncate</tt> with the old API that accepts the
# +length+ as its optional second and the +ellipsis+ as its
# optional third parameter:
# truncate("Once upon a time in a world far far away", 14)
# # => Once upon a...
# # => "Once upon a..."
#
# truncate("And they found that many people were sleeping better.", 25, "... (continued)")
# # => And they f... (continued)
# # => "And they f... (continued)"
def truncate(text, *args)
options = args.extract_options!
unless args.empty?
......
......@@ -31,6 +31,7 @@ def exists?(*args)
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
......
......@@ -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
......
......@@ -9,7 +9,7 @@ module QueryMethods
(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 @@ def #{query_method}(*args, &block)
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)
......
......@@ -112,6 +112,11 @@ def test_finding_with_group
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
......
......@@ -20,25 +20,21 @@ def squish!
self
end
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>.
# The last characters will be replaced with the <tt>:omission</tt> (defaults to "...")
# for a total length not exceeding <tt>:length</tt>.
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
#
# Pass a <tt>:separator</tt> to truncate +text+ at a natural break.
# "Once upon a time in a world far far away".truncate(27)
# # => "Once upon a time in a wo..."
#
# ==== Examples
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
# for a total length not exceeding <tt>:length</tt>:
#
# "Once upon a time in a world far far away".truncate(30)
# # => Once upon a time in a worl...
# "Once upon a time in a world far far away".truncate(27, :separator => ' ')
# # => "Once upon a time in a..."
#
# "Once upon a time in a world far far away".truncate(30, :separator => ' ')
# # => Once upon a time in a world...
#
# "Once upon a time in a world far far away".truncate(14)
# # => Once upon a...
# Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
#
# "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
# # => And they f... (continued)
# # => "And they f... (continued)"
def truncate(length, options = {})
text = self.dup
options[:omission] ||= "..."
......
*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)*
......
......@@ -699,7 +699,7 @@ Creates a scope around a specific model object like form_for, but doesn‘t crea
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
<% fields_for @person.permission do |permission_fields| %>
<%= fields_for @person.permission do |permission_fields| %>
Admin? : <%= permission_fields.check_box :admin %>
<% end %>
<% end %>
......
......@@ -1254,6 +1254,39 @@ There's also the destructive version +String#squish!+.
NOTE: Defined in +active_support/core_ext/string/filters.rb+.
h4. +truncate+
The method +truncate+ returns a copy of its receiver truncated after a given +length+:
<ruby>
"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."
</ruby>
Ellipsis can be customized with the +:omission+ option:
<ruby>
"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '&hellip;')
# => "Oh dear! Oh &hellip;"
</ruby>
Note in particular that truncation takes into account the length of the omission string.
Pass a +:separator+ to truncate the string at a natural break:
<ruby>
"Oh dear! Oh dear! I shall be late!".truncate(18)
# => "Oh dear! Oh dea..."
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ')
# => "Oh dear! Oh..."
</ruby>
In the above example "dear" gets cut first, but then +:separator+ prevents it.
WARNING: The option +:separator+ can't be a regexp.
NOTE: Defined in +active_support/core_ext/string/filters.rb+.
h4. Key-based Interpolation
In Ruby 1.9 the <tt>%</tt> string operator supports key-based interpolation, both formatted and unformatted:
......
......@@ -879,32 +879,28 @@ Here is a list with all the available Active Record callbacks, listed in the sam
h4. Creating an Object
* +before_validation+
* +before_validation_on_create+
* +after_validation+
* +after_validation_on_create+
* +before_save+
* +after_save+
* +before_create+
* INSERT OPERATION
* +around_create+
* +after_create+
* +after_save+
h4. Updating an Object
* +before_validation+
* +before_validation_on_update+
* +after_validation+
* +after_validation_on_update+
* +before_save+
* +after_save+
* +before_update+
* UPDATE OPERATION
* +around_update+
* +after_update+
* +after_save+
h4. Destroying an Object
* +before_destroy+
* DELETE OPERATION
* +after_destroy+
* +around_destroy+
WARNING. +after_save+ runs both on create and update, but always _after_ the more specific callbacks +after_create+ and +after_update+, no matter the order in which the macro calls were executed.
......
......@@ -322,14 +322,10 @@ config.generators do |g|
g.template_engine :erb
g.test_framework :shoulda, :fixture => false
g.stylesheets false
end
</ruby>
And at the end of the same file:
<ruby>
require 'rails/generators'
Rails::Generators.fallbacks[:shoulda] = :test_unit
# Add a fallback!
g.fallbacks[:should] = :test_unit
end
</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:
......@@ -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
......
......@@ -1342,7 +1342,7 @@ We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make
Now create the folder <tt>app/views/tags</tt> and make a file in there called <tt>_form.html.erb</tt> which contains the form for the tag:
<erb>
<% form.fields_for :tags do |tag_form| %>
<%= form.fields_for :tags do |tag_form| %>
<div class="field">
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
......
......@@ -143,7 +143,7 @@ Now add a nested form for the +address+ association:
<%= form_for @person do |f| %>
<%= f.text_field :name %>
<% f.fields_for :address do |af| %>
<%= f.fields_for :address do |af| %>
<%= f.text_field :street %>
<% end %>
<% end %>
......@@ -184,7 +184,7 @@ The form code for an association collection is pretty similar to that of a singl
<%= form_for @person do |f| %>
<%= f.text_field :name %>
<% f.fields_for :projects do |pf| %>
<%= f.fields_for :projects do |pf| %>
<%= f.text_field :name %>
<% end %>
<% end %>
......
......@@ -67,6 +67,7 @@ def inherited(base)
raise "You cannot have more than one Rails::Application" if Rails.application
super
Rails.application = base.instance
Rails.application.add_lib_to_load_paths!
ActiveSupport.run_load_hooks(:before_configuration, base.instance)
end
......@@ -83,11 +84,21 @@ def method_missing(*args, &block)
delegate :middleware, :to => :config
def add_lib_to_load_paths!
path = config.root.join('lib').to_s
$LOAD_PATH.unshift(path) if File.exists?(path)
end
def require_environment!
environment = paths.config.environment.to_a.first
require environment if environment
end
def eager_load!
railties.all(&:eager_load!)
super
end
def routes
@routes ||= ActionDispatch::Routing::RouteSet.new
end
......
......@@ -38,7 +38,7 @@ module Finisher
initializer :eager_load! do
if config.cache_classes && !$rails_rake_task
ActiveSupport.run_load_hooks(:before_eager_load, self)
railties.all(&:eager_load!)
eager_load!
end
end
......
require 'rails/generators'
Rails::Generators.configure!
if [nil, "-h", "--help"].include?(ARGV.first)
Rails::Generators.help 'destroy'
......
require 'rails/generators'
Rails::Generators.configure!
if [nil, "-h", "--help"].include?(ARGV.first)
Rails::Generators.help 'generate'
......
......@@ -68,6 +68,7 @@ def self.configure!(config = Rails.application.config.generators) #:nodoc:
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 @@ def self.namespaces_to_paths(namespaces) #:nodoc:
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
\ No newline at end of file
......@@ -19,6 +19,23 @@ def setup
assert $:.include?("#{app_path}/app/models")
end
test "initializing an application adds lib path on inheritance hook" do
app_file "lib/foo.rb", <<-RUBY
module Foo; end
RUBY
add_to_config <<-RUBY
require "foo"
raise "Expected Foo to be defined" unless defined?(Foo)
RUBY
assert_nothing_raised do
require "#{app_path}/config/environment"
end
assert $:.include?("#{app_path}/lib")
end
test "initializing an application eager load any path under app" do
app_file "app/anything/foo.rb", <<-RUBY
module Foo; end
......
require 'abstract_unit'
require 'rails/generators'
require 'rails/generators/test_case'
module Rails
def self.root
......@@ -8,8 +10,9 @@ def self.root
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'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册