mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Merge branch 'master' of github.com:rails/rails
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'active_support/configurable'
|
||||
require 'active_support/core_ext/module/anonymous'
|
||||
|
||||
module AbstractController
|
||||
class Error < StandardError; end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require "abstract_controller/base"
|
||||
require "action_view"
|
||||
|
||||
module AbstractController
|
||||
class DoubleRenderError < Error
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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+
|
||||
|
||||
@@ -43,25 +43,25 @@ module ActionView
|
||||
# ==== 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 @@ 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
|
||||
|
||||
@@ -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 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,25 +20,21 @@ class String
|
||||
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] ||= "..."
|
||||
|
||||
@@ -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)*
|
||||
|
||||
|
||||
@@ -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 => '…')
|
||||
# => "Oh dear! Oh …"
|
||||
</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+
|
||||
* +before_create+
|
||||
* INSERT OPERATION
|
||||
* +after_create+
|
||||
* +after_save+
|
||||
* +before_create+
|
||||
* +around_create+
|
||||
* +after_create+
|
||||
|
||||
h4. Updating an Object
|
||||
|
||||
* +before_validation+
|
||||
* +before_validation_on_update+
|
||||
* +after_validation+
|
||||
* +after_validation_on_update+
|
||||
* +before_save+
|
||||
* +before_update+
|
||||
* UPDATE OPERATION
|
||||
* +after_update+
|
||||
* +after_save+
|
||||
* +before_update+
|
||||
* +around_update+
|
||||
* +after_update+
|
||||
|
||||
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,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
|
||||
|
||||
|
||||
@@ -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 @@ module Rails
|
||||
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 @@ module Rails
|
||||
|
||||
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 Rails
|
||||
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
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'rails/generators'
|
||||
Rails::Generators.configure!
|
||||
|
||||
if [nil, "-h", "--help"].include?(ARGV.first)
|
||||
Rails::Generators.help 'destroy'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'rails/generators'
|
||||
Rails::Generators.configure!
|
||||
|
||||
if [nil, "-h", "--help"].include?(ARGV.first)
|
||||
Rails::Generators.help 'generate'
|
||||
|
||||
@@ -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
|
||||
@@ -19,6 +19,23 @@ module ApplicationTests
|
||||
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
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user