Permalink
Browse files

Merge commit 'mainstream/master'

Conflicts:

	railties/doc/guides/html/layouts_and_rendering.html
	railties/doc/guides/source/active_record_basics.txt
	railties/doc/guides/source/layouts_and_rendering.txt
  • Loading branch information...
lifo committed Nov 1, 2008
2 parents a3aa0c1 + 5a02f0b commit 1147453fce0890ea229c3af5f43c909ebe53061e
Showing with 697 additions and 338 deletions.
  1. +11 −0 actionpack/CHANGELOG
  2. +54 −5 actionpack/lib/action_controller/base.rb
  3. +4 −0 actionpack/lib/action_controller/dispatcher.rb
  4. +19 −7 actionpack/lib/action_controller/routing/optimisations.rb
  5. +1 −7 actionpack/lib/action_controller/routing/recognition_optimisation.rb
  6. +1 −1 actionpack/lib/action_controller/test_process.rb
  7. +8 −3 actionpack/lib/action_view/base.rb
  8. +1 −1 actionpack/lib/action_view/helpers/asset_tag_helper.rb
  9. +4 −5 actionpack/lib/action_view/helpers/translation_helper.rb
  10. +14 −3 actionpack/lib/action_view/helpers/url_helper.rb
  11. +1 −1 actionpack/lib/action_view/partials.rb
  12. +10 −4 actionpack/lib/action_view/renderable.rb
  13. +10 −0 actionpack/test/controller/redirect_test.rb
  14. +20 −0 actionpack/test/controller/render_test.rb
  15. +2 −0 actionpack/test/fixtures/layouts/_column.html.erb
  16. +1 −1 actionpack/test/fixtures/test/_customer.erb
  17. +3 −0 actionpack/test/fixtures/test/nested_layout.erb
  18. +1 −0 actionpack/test/fixtures/test/template.erb
  19. +8 −0 actionpack/test/template/asset_tag_helper_test.rb
  20. +18 −0 actionpack/test/template/render_test.rb
  21. +2 −2 actionpack/test/template/translation_helper_test.rb
  22. +23 −0 actionpack/test/template/url_helper_test.rb
  23. +7 −0 activerecord/CHANGELOG
  24. +12 −9 activerecord/lib/active_record/associations.rb
  25. +1 −1 activerecord/lib/active_record/attribute_methods.rb
  26. +8 −7 activerecord/lib/active_record/base.rb
  27. +14 −28 activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
  28. +79 −68 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  29. +12 −6 activerecord/lib/active_record/schema_dumper.rb
  30. +7 −4 activerecord/test/cases/attribute_methods_test.rb
  31. +6 −0 activerecord/test/cases/base_test.rb
  32. +11 −0 activerecord/test/cases/finder_test.rb
  33. +5 −0 activeresource/CHANGELOG
  34. +1 −1 activeresource/lib/active_resource/custom_methods.rb
  35. +2 −0 activeresource/test/base/custom_methods_test.rb
  36. +9 −0 activesupport/CHANGELOG
  37. +1 −1 activesupport/lib/active_support/core_ext/array/conversions.rb
  38. +2 −2 activesupport/lib/active_support/deprecation.rb
  39. +1 −1 activesupport/lib/active_support/string_inquirer.rb
  40. +11 −4 activesupport/lib/active_support/vendor/i18n-0.0.1/i18n.rb
  41. +20 −16 activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb
  42. +7 −0 railties/CHANGELOG
  43. +1 −1 railties/Rakefile
  44. +1 −1 railties/doc/guides/source/active_record_basics.txt
  45. +218 −119 railties/html/javascripts/prototype.js
  46. +1 −0 railties/lib/initializer.rb
  47. +24 −13 railties/lib/rails/gem_dependency.rb
  48. +10 −10 railties/lib/rails_generator/generators/components/plugin/plugin_generator.rb
  49. +1 −0 railties/lib/rails_generator/generators/components/plugin/templates/Rakefile
  50. +3 −0 railties/lib/rails_generator/generators/components/plugin/templates/test_helper.rb
  51. +2 −2 railties/lib/rails_generator/generators/components/plugin/templates/unit_test.rb
  52. +2 −1 railties/lib/tasks/gems.rake
  53. +2 −3 railties/test/gem_dependency_test.rb
View
@@ -1,3 +1,14 @@
+*2.2.1 [RC2 or 2.2 final]*
+
+* Simplified the logging format for parameters (don't include controller, action, and format as duplicates) [DHH]
+
+* Remove the logging of the Session ID when the session store is CookieStore [DHH]
+
+* Fixed regex in redirect_to to fully support URI schemes #1247 [Seth Fitzsimmons]
+
+* Fixed bug with asset timestamping when using relative_url_root #1265 [Joe Goldwasser]
+
+
*2.2.0 [RC1] (October 24th, 2008)*
* Fix incorrect closing CDATA delimiter and that HTML::Node.parse would blow up on unclosed CDATA sections [packagethief]
@@ -801,6 +801,19 @@ def append_view_path(path)
# # Renders "Hello from code!"
# render :text => proc { |response, output| output.write("Hello from code!") }
#
+ # === Rendering XML
+ #
+ # Rendering XML sets the content type to application/xml.
+ #
+ # # Renders '<name>David</name>'
+ # render :xml => {:name => "David"}.to_xml
+ #
+ # It's not necessary to call <tt>to_xml</tt> on the object you want to render, since <tt>render</tt> will
+ # automatically do that for you:
+ #
+ # # Also renders '<name>David</name>'
+ # render :xml => {:name => "David"}
+ #
# === Rendering JSON
#
# Rendering JSON sets the content type to application/json and optionally wraps the JSON in a callback. It is expected
@@ -846,8 +859,14 @@ def append_view_path(path)
# page.visual_effect :highlight, 'user_list'
# end
#
- # === Rendering with status and location headers
+ # === Rendering vanilla JavaScript
+ #
+ # In addition to using RJS with render :update, you can also just render vanilla JavaScript with :js.
+ #
+ # # Renders "alert('hello')" and sets the mime type to text/javascript
+ # render :js => "alert('hello')"
#
+ # === Rendering with status and location headers
# All renders take the <tt>:status</tt> and <tt>:location</tt> options and turn them into headers. They can even be used together:
#
# render :xml => post.to_xml, :status => :created, :location => post_url(post)
@@ -898,6 +917,10 @@ def render(options = nil, extra_options = {}, &block) #:doc:
response.content_type ||= Mime::XML
render_for_text(xml.respond_to?(:to_xml) ? xml.to_xml : xml, options[:status])
+ elsif js = options[:js]
+ response.content_type ||= Mime::JS
+ render_for_text(js, options[:status])
+
elsif json = options[:json]
json = json.to_json unless json.is_a?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
@@ -933,6 +956,7 @@ def render(options = nil, extra_options = {}, &block) #:doc:
def render_to_string(options = nil, &block) #:doc:
render(options, &block)
ensure
+ response.content_type = nil
erase_render_results
reset_variables_added_to_assigns
end
@@ -1056,7 +1080,10 @@ def redirect_to(options = {}, response_status = {}) #:doc:
logger.info("Redirected to #{options}") if logger && logger.info?
case options
- when %r{^\w+://.*}
+ # The scheme name consist of a letter followed by any combination of
+ # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
+ # characters; and is terminated by a colon (":").
+ when %r{^\w[\w\d+.-]*:.*}
redirect_to_full_url(options, status)
when String
redirect_to_full_url(request.protocol + request.host_with_port + options, status)
@@ -1201,11 +1228,33 @@ def initialize_current_url
def log_processing
if logger && logger.info?
- logger.info "\n\nProcessing #{self.class.name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
- logger.info " Session ID: #{@_session.session_id}" if @_session and @_session.respond_to?(:session_id)
- logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(params).inspect : params.inspect}"
+ log_processing_for_request_id
+ log_processing_for_session_id
+ log_processing_for_parameters
end
end
+
+ def log_processing_for_request_id
+ request_id = "\n\nProcessing #{self.class.name}\##{action_name} "
+ request_id << "to #{params[:format]} " if params[:format]
+ request_id << "(for #{request_origin}) [#{request.method.to_s.upcase}]"
+
+ logger.info(request_id)
+ end
+
+ def log_processing_for_session_id
+ if @_session && @_session.respond_to?(:session_id) && @_session.respond_to?(:dbman) &&
+ !@_session.dbman.is_a?(CGI::Session::CookieStore)
+ logger.info " Session ID: #{@_session.session_id}"
+ end
+ end
+
+ def log_processing_for_parameters
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params
+ parameters = parameters.except(:controller, :action, :format)
+
+ logger.info " Parameters: #{parameters.inspect}"
+ end
def default_render #:nodoc:
render
@@ -28,6 +28,10 @@ def define_dispatcher_callbacks(cache_classes)
end
after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
+
+ to_prepare do
+ I18n.reload!
+ end
end
# Backward-compatible class method takes CGI-specific args. Deprecated
@@ -20,14 +20,20 @@ def generate_optimisation_block(route, kind)
class Optimiser
attr_reader :route, :kind
+ GLOBAL_GUARD_CONDITIONS = [
+ "(!defined?(default_url_options) || default_url_options.blank?)",
+ "(!defined?(controller.default_url_options) || controller.default_url_options.blank?)",
+ "defined?(request)",
+ "request"
+ ]
def initialize(route, kind)
@route = route
@kind = kind
end
- def guard_condition
- 'false'
+ def guard_conditions
+ ["false"]
end
def generation_code
@@ -36,6 +42,7 @@ def generation_code
def source_code
if applicable?
+ guard_condition = (GLOBAL_GUARD_CONDITIONS + guard_conditions).join(" && ")
"return #{generation_code} if #{guard_condition}\n"
else
"\n"
@@ -57,14 +64,14 @@ def applicable?
# return a string like "/people/#{@person.to_param}"
# rather than triggering the expensive logic in +url_for+.
class PositionalArguments < Optimiser
- def guard_condition
+ def guard_conditions
number_of_arguments = route.segment_keys.size
# if they're using foo_url(:id=>2) it's one
# argument, but we don't want to generate /foos/id2
if number_of_arguments == 1
- "(!defined?(default_url_options) || default_url_options.blank?) && defined?(request) && request && args.size == 1 && !args.first.is_a?(Hash)"
+ ["args.size == 1", "!args.first.is_a?(Hash)"]
else
- "(!defined?(default_url_options) || default_url_options.blank?) && defined?(request) && request && args.size == #{number_of_arguments}"
+ ["args.size == #{number_of_arguments}"]
end
end
@@ -98,8 +105,13 @@ def generation_code
# above, but it supports additional query parameters as the last
# argument
class PositionalArgumentsWithAdditionalParams < PositionalArguments
- def guard_condition
- "(!defined?(default_url_options) || default_url_options.blank?) && defined?(request) && request && args.size == #{route.segment_keys.size + 1} && !args.last.has_key?(:anchor) && !args.last.has_key?(:port) && !args.last.has_key?(:host)"
+ def guard_conditions
+ [
+ "args.size == #{route.segment_keys.size + 1}",
+ "!args.last.has_key?(:anchor)",
+ "!args.last.has_key?(:port)",
+ "!args.last.has_key?(:host)"
+ ]
end
# This case uses almost the same code as positional arguments,
@@ -153,13 +153,7 @@ def recognize_optimized(path, env)
def clear_recognize_optimized!
remove_recognize_optimized!
-
- class << self
- def recognize_optimized(path, environment)
- write_recognize_optimized!
- recognize_optimized(path, environment)
- end
- end
+ write_recognize_optimized!
end
def remove_recognize_optimized!
@@ -218,7 +218,7 @@ def redirect_url_match?( pattern )
# Returns the template of the file which was used to
# render this response (or nil)
def rendered_template
- template.send(:_first_render)
+ template.instance_variable_get(:@_first_render)
end
# A shortcut to the flash. Returns an empty hash if no session flash exists.
@@ -222,6 +222,7 @@ def include(*args)
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc:
@assigns = assigns_for_first_render
@assigns_added = nil
+ @_render_stack = []
@controller = controller
@helpers = ProxyModule.new(self)
self.view_paths = view_paths
@@ -271,9 +272,13 @@ def template_format
end
end
- private
- attr_accessor :_first_render, :_last_render
+ # Access the current template being rendered.
+ # Returns a ActionView::Template object.
+ def template
+ @_render_stack.last
+ end
+ private
# Evaluates the local assigns and controller ivars, pushes them to the view.
def _evaluate_assigns_and_ivars #:nodoc:
unless @assigns_added
@@ -312,7 +317,7 @@ def _pick_template(template_path)
template
elsif template = self.view_paths[template_file_name]
template
- elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
+ elsif @_render_stack.first && template = self.view_paths["#{template_file_name}.#{@_render_stack.first.format_and_extension}"]
template
elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
@template_format = :html
@@ -588,8 +588,8 @@ def compute_public_path(source)
source += ".#{extension}" if missing_extension?(source)
unless source =~ ProtocolRegexp
source = "/#{directory}/#{source}" unless source[0] == ?/
- source = prepend_relative_url_root(source)
source = rewrite_asset_path(source)
+ source = prepend_relative_url_root(source)
end
source = prepend_asset_host(source)
source
@@ -3,12 +3,11 @@
module ActionView
module Helpers
module TranslationHelper
- def translate(*args)
- args << args.extract_options!.merge(:raise => true)
- I18n.translate *args
-
+ def translate(key, options = {})
+ options[:raise] = true
+ I18n.translate(key, options)
rescue I18n::MissingTranslationData => e
- keys = I18n.send :normalize_translation_keys, e.locale, e.key, e.options[:scope]
+ keys = I18n.send(:normalize_translation_keys, e.locale, e.key, e.options[:scope])
content_tag('span', keys.join(', '), :class => 'translation_missing')
end
alias :t :translate
@@ -499,14 +499,17 @@ def mail_to(email_address, name = nil, html_options = {})
# True if the current request URI was generated by the given +options+.
#
# ==== Examples
- # Let's say we're in the <tt>/shop/checkout</tt> action.
+ # Let's say we're in the <tt>/shop/checkout?order=desc</tt> action.
#
# current_page?(:action => 'process')
# # => false
#
# current_page?(:controller => 'shop', :action => 'checkout')
# # => true
#
+ # current_page?(:controller => 'shop', :action => 'checkout', :order => 'asc)
+ # # => false
+ #
# current_page?(:action => 'checkout')
# # => true
#
@@ -515,10 +518,18 @@ def mail_to(email_address, name = nil, html_options = {})
def current_page?(options)
url_string = CGI.escapeHTML(url_for(options))
request = @controller.request
+ # We ignore any extra parameters in the request_uri if the
+ # submitted url doesn't have any either. This lets the function
+ # work with things like ?order=asc
+ if url_string.index("?")
+ request_uri = request.request_uri
+ else
+ request_uri = request.request_uri.split('?').first
+ end
if url_string =~ /^\w+:\/\//
- url_string == "#{request.protocol}#{request.host_with_port}#{request.request_uri}"
+ url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
else
- url_string == request.request_uri
+ url_string == request_uri
end
end
@@ -181,7 +181,7 @@ def render_partial_collection(options = {}) #:nodoc:
ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
template = _pick_partial_template(_partial_path)
local_assigns[template.counter_name] = index
- result = template.render_partial(self, object, local_assigns, as)
+ result = template.render_partial(self, object, local_assigns.dup, as)
index += 1
result
end.join(spacer)
@@ -25,20 +25,26 @@ def compiled_source
def render(view, local_assigns = {})
compile(local_assigns)
- view.send(:_first_render=, self) unless view.send(:_first_render)
- view.send(:_last_render=, self)
+ stack = view.instance_variable_get(:@_render_stack)
+ stack.push(self)
+
+ # This is only used for TestResponse to set rendered_template
+ view.instance_variable_set(:@_first_render, self) unless view.instance_variable_get(:@_first_render)
view.send(:_evaluate_assigns_and_ivars)
view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type)
- view.send(method_name(local_assigns), local_assigns) do |*names|
+ result = view.send(method_name(local_assigns), local_assigns) do |*names|
ivar = :@_proc_for_layout
- if view.instance_variable_defined?(ivar) and proc = view.instance_variable_get(ivar)
+ if !view.instance_variable_defined?(:"@content_for_#{names.first}") && view.instance_variable_defined?(ivar) && (proc = view.instance_variable_get(ivar))
view.capture(*names, &proc)
elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}")
view.instance_variable_get(ivar)
end
end
+
+ stack.pop
+ result
end
def method_name(local_assigns)
@@ -73,6 +73,10 @@ def redirect_to_url_with_unescaped_query_string
redirect_to "http://dev.rubyonrails.org/query?status=new"
end
+ def redirect_to_url_with_complex_scheme
+ redirect_to "x-test+scheme.complex:redirect"
+ end
+
def redirect_to_back
redirect_to :back
end
@@ -198,6 +202,12 @@ def test_redirect_to_url_with_unescaped_query_string
assert_redirected_to "http://dev.rubyonrails.org/query?status=new"
end
+ def test_redirect_to_url_with_complex_scheme
+ get :redirect_to_url_with_complex_scheme
+ assert_response :redirect
+ assert_equal "x-test+scheme.complex:redirect", redirect_to_url
+ end
+
def test_redirect_to_back
@request.env["HTTP_REFERER"] = "http://www.example.com/coming/from"
get :redirect_to_back
Oops, something went wrong.

0 comments on commit 1147453

Please sign in to comment.