diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 54c7771f4c53129bebcee8b6c5cbe53f360e247a..faa0d674dcff0de7fc694aa2df5cb9996ebf5f4d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -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] diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 8500cbd7f2ee5c64addd29e4968bc30ffbfdf0c9..ff97a7e76ab76e0697f7c0017e74cfeab1db77b1 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -1,4 +1,5 @@ require 'active_support/configurable' +require 'active_support/core_ext/module/anonymous' module AbstractController class Error < StandardError; end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index d2db366140a2fd3cbc0f6e267d0d3ef2ecae48c2..6e3998aa21b46499b95666bddad5e626a338d3e8 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,4 +1,5 @@ require "abstract_controller/base" +require "action_view" module AbstractController class DoubleRenderError < Error diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 060117756e2915f7c9e9235b619a807f57a390f5..508ea6e2b7fbb4841e5d18cbdbec41dfbf268dd4 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -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 diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 2ba0d6e5cdaf1a93a755d1cebc2182bb4278e464..8c25b147efc3ad3b017d192a4f3ec534c912a244 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -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+ diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 860c1de6af952eb46190455eb9fe605435b23b41..bfad9f8d316a982701a4006632625c183e4e9327 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -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 truncate 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? diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 35927d09d16530b3da42098df83d61bd912074f2..7f5e5d11b82d252b8ec9049523e83703d1ea0ce8 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -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 diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index cb7eade0abe9ef68d3290042d76075934313eedf..952f2a30701e69659363ca36493c66993dab14f7 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -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 diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 6782554854f02a2cbf14911328bd4f5f27b9c195..7a48a6596aa96c0a35d78c3da53ecffb46a8b6c5 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -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) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index b6815af67e99b6d95628d1d49428698bd3290f93..4097c5119ec4468b5d0f876c6e967fc6a41cf559 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -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 diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index cdd86a836f30c3a1cd39a7aef9189b6511445bf7..e15a1df9c9e3b0d1eec6a899a3b03ee4b2363823 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -20,25 +20,21 @@ def squish! self end - # Truncates a given +text+ after a given length if +text+ is longer than length. - # The last characters will be replaced with the :omission (defaults to "...") - # for a total length not exceeding :length. + # Truncates a given +text+ after a given length if +text+ is longer than length: # - # Pass a :separator 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 :omission string (defaults to "...") + # for a total length not exceeding :length: # - # "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 :separator 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] ||= "..." diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 1d76c77ade2e56e689ac5638aceee0fa6e2d80af..fe3ab3cdcf2160a927b01cd4e04eb299f12c71ab 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -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)* diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index 43ebe8787513d6d86791ad21c5cab6298e237205..8b5eda0973b98ce1273e6eb59d59ec1187f20c74 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -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 %> diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 08fddd2926fc39242412518bc323026d0054ef9d..de82e871a6d21c57055520da73dbc4d2402615d0 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -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+: + + +"Oh dear! Oh dear! I shall be late!".truncate(20) +# => "Oh dear! Oh dear!..." + + +Ellipsis can be customized with the +:omission+ option: + + +"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '…') +# => "Oh dear! Oh …" + + +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: + + +"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..." + + +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 % string operator supports key-based interpolation, both formatted and unformatted: diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index 857551c9d5b57b0e5b49cf5b2afa995ef3d9ec22..d83ea578641135aa19a5c4deb1e6a3dd8c3e6998 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -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. diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index d3757e97335e2987362274ca703c6707543a3a8f..b77a2837c3217091920c64fe54c0ace0acaf1a85 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -322,14 +322,10 @@ config.generators do |g| g.template_engine :erb g.test_framework :shoulda, :fixture => false g.stylesheets false -end - - -And at the end of the same file: - -require 'rails/generators' -Rails::Generators.fallbacks[:shoulda] = :test_unit + # Add a fallback! + g.fallbacks[:should] = :test_unit +end 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 -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 diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index fe623e969f12795e178f3fd7a7dfbce12299865b..46e709d0f5cd9bbd255852a7dc7c00e7ab0121b5 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1342,7 +1342,7 @@ We also add a @post.tags.build at the top of this form, this is to make Now create the folder app/views/tags and make a file in there called _form.html.erb which contains the form for the tag: -<% form.fields_for :tags do |tag_form| %> +<%= form.fields_for :tags do |tag_form| %>
<%= tag_form.label :name, 'Tag:' %> <%= tag_form.text_field :name %> diff --git a/railties/guides/source/nested_model_forms.textile b/railties/guides/source/nested_model_forms.textile index 4a79902232ebc495d8d7ff0fb397f5a1dce9b94a..39b0c32f2459aee2d691de10023fefe911749627 100644 --- a/railties/guides/source/nested_model_forms.textile +++ b/railties/guides/source/nested_model_forms.textile @@ -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 %> diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7416e94eeb02ddba9c991d7a4af8d989acf87b64..85ae8cbbb106e200776ec8f14c57e392a4ff7cd6 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -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 diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index fbab4d551535b5a08b8ce6535c1799dfa2cae376..d7ff4893365a455c68ee4f5864ca1ab8ad22bb21 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -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 diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index 9023c61bf243fabfdba02483ec9ac0522aaac6dc..db59cd8ad9de69d7e68827110737ffefbfc553ee 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -1,4 +1,5 @@ require 'rails/generators' +Rails::Generators.configure! if [nil, "-h", "--help"].include?(ARGV.first) Rails::Generators.help 'destroy' diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index 7d05a30de818778ab60b41ebe500ab3fbcb33af1..1b3eef504ac0b4771bdba0bffa0689c510ecd0b3 100755 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -1,4 +1,5 @@ require 'rails/generators' +Rails::Generators.configure! if [nil, "-h", "--help"].include?(ARGV.first) Rails::Generators.help 'generate' diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index fe8a6c0b94b9207bcfbebcaa264d7faec92b15d3..af927570531dab9790b0889a8ff01eecd4b8d844 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -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 diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb index b39b9ecaae5583104ebb71f96c60fa298de91b3d..d31915e1299a7b565ae1dff9c6c57269a626b326 100644 --- a/railties/test/application/initializers/load_path_test.rb +++ b/railties/test/application/initializers/load_path_test.rb @@ -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 diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index d8bdb344f2047265b30d966af0a6d5d86aed8071..4a5a9b2932d840bd606e359d3d1051331803d335 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -1,4 +1,6 @@ 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'