aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2009-07-21 12:51:53 +0200
committerJosé Valim <jose.valim@gmail.com>2009-07-21 12:51:53 +0200
commit33048b6e2738ff73b612dbcb35955189221dfbd0 (patch)
tree7e32f6031199c1e7ee9a3e5a15789b5f568a565d /actionpack
parentedda0bfe76fc9b2adcdb705665aaef2769e6ef03 (diff)
parent9d7aae710384fb5f04129c35b86c5ea5fb9d83a9 (diff)
downloadrails-33048b6e2738ff73b612dbcb35955189221dfbd0.tar.gz
rails-33048b6e2738ff73b612dbcb35955189221dfbd0.tar.bz2
rails-33048b6e2738ff73b612dbcb35955189221dfbd0.zip
Solving merge conflicts.
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/examples/very_simple.rb50
-rw-r--r--actionpack/examples/views/layouts/alt.html.erb1
-rw-r--r--actionpack/examples/views/layouts/kaigi.html.erb1
-rw-r--r--actionpack/examples/views/template.html.erb1
-rw-r--r--actionpack/lib/action_controller.rb16
-rw-r--r--actionpack/lib/action_controller/abstract/base.rb2
-rw-r--r--actionpack/lib/action_controller/abstract/callbacks.rb2
-rw-r--r--actionpack/lib/action_controller/abstract/helpers.rb6
-rw-r--r--actionpack/lib/action_controller/abstract/layouts.rb5
-rw-r--r--actionpack/lib/action_controller/abstract/logger.rb1
-rw-r--r--actionpack/lib/action_controller/abstract/renderer.rb19
-rw-r--r--actionpack/lib/action_controller/base/compatibility.rb4
-rw-r--r--actionpack/lib/action_controller/base/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/base/http.rb1
-rw-r--r--actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb1
-rw-r--r--actionpack/lib/action_controller/testing/process.rb1
-rw-r--r--actionpack/lib/action_view.rb4
-rw-r--r--actionpack/lib/action_view/base.rb13
-rw-r--r--actionpack/lib/action_view/context.rb44
-rw-r--r--actionpack/lib/action_view/helpers.rb5
-rw-r--r--actionpack/lib/action_view/helpers/active_model_helper.rb (renamed from actionpack/lib/action_view/helpers/active_record_helper.rb)26
-rw-r--r--actionpack/lib/action_view/helpers/ajax_helper.rb68
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb35
-rw-r--r--actionpack/lib/action_view/render/partials.rb6
-rw-r--r--actionpack/lib/action_view/template/renderable.rb8
-rw-r--r--actionpack/lib/action_view/template/template.rb2
-rw-r--r--actionpack/lib/action_view/test_case.rb1
-rw-r--r--actionpack/test/abstract_unit.rb3
-rw-r--r--actionpack/test/activerecord/render_partial_with_record_identification_test.rb1
-rw-r--r--actionpack/test/controller/record_identifier_test.rb1
-rw-r--r--actionpack/test/controller/redirect_test.rb1
-rw-r--r--actionpack/test/javascript/ajax_test.rb115
-rw-r--r--actionpack/test/lib/controller/fake_models.rb2
-rw-r--r--actionpack/test/template/active_record_helper_i18n_test.rb3
-rw-r--r--actionpack/test/template/active_record_helper_test.rb21
-rw-r--r--actionpack/test/template/atom_feed_helper_test.rb10
-rw-r--r--actionpack/test/template/compiled_templates_test.rb2
-rw-r--r--actionpack/test/template/form_helper_test.rb27
-rw-r--r--actionpack/test/template/prototype_helper_test.rb10
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb3
-rw-r--r--actionpack/test/template/url_helper_test.rb2
41 files changed, 438 insertions, 88 deletions
diff --git a/actionpack/examples/very_simple.rb b/actionpack/examples/very_simple.rb
new file mode 100644
index 0000000000..8d01cb39bd
--- /dev/null
+++ b/actionpack/examples/very_simple.rb
@@ -0,0 +1,50 @@
+$:.push "rails/activesupport/lib"
+$:.push "rails/actionpack/lib"
+
+require "action_controller"
+
+class Kaigi < ActionController::Http
+ include AbstractController::Callbacks
+ include ActionController::RackConvenience
+ include ActionController::Renderer
+ include ActionController::Layouts
+ include ActionView::Context
+
+ before_filter :set_name
+ append_view_path "views"
+
+ def _action_view
+ self
+ end
+
+ def controller
+ self
+ end
+
+ DEFAULT_LAYOUT = Object.new.tap {|l| def l.render(*) yield end }
+
+ def _render_template_from_controller(template, layout = DEFAULT_LAYOUT, options = {}, partial = false)
+ ret = template.render(self, {})
+ layout.render(self, {}) { ret }
+ end
+
+ def index
+ render :template => "template"
+ end
+
+ def alt
+ render :template => "template", :layout => "alt"
+ end
+
+ private
+ def set_name
+ @name = params[:name]
+ end
+end
+
+app = Rack::Builder.new do
+ map("/kaigi") { run Kaigi.action(:index) }
+ map("/kaigi/alt") { run Kaigi.action(:alt) }
+end.to_app
+
+Rack::Handler::Mongrel.run app, :Port => 3000 \ No newline at end of file
diff --git a/actionpack/examples/views/layouts/alt.html.erb b/actionpack/examples/views/layouts/alt.html.erb
new file mode 100644
index 0000000000..c4816337a6
--- /dev/null
+++ b/actionpack/examples/views/layouts/alt.html.erb
@@ -0,0 +1 @@
++ <%= yield %> + \ No newline at end of file
diff --git a/actionpack/examples/views/layouts/kaigi.html.erb b/actionpack/examples/views/layouts/kaigi.html.erb
new file mode 100644
index 0000000000..274607a96a
--- /dev/null
+++ b/actionpack/examples/views/layouts/kaigi.html.erb
@@ -0,0 +1 @@
+Hello <%= yield %> Goodbye \ No newline at end of file
diff --git a/actionpack/examples/views/template.html.erb b/actionpack/examples/views/template.html.erb
new file mode 100644
index 0000000000..3108e9ad70
--- /dev/null
+++ b/actionpack/examples/views/template.html.erb
@@ -0,0 +1 @@
+Hello <%= @name %> \ No newline at end of file
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index e822a11d14..32572c93c0 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -52,11 +52,21 @@ module ActionController
autoload :SessionOverflowError, 'action_controller/base/exceptions'
autoload :UnknownHttpMethod, 'action_controller/base/exceptions'
- require 'action_controller/routing'
+ autoload :Routing, 'action_controller/routing'
end
autoload :HTML, 'action_controller/vendor/html-scanner'
autoload :AbstractController, 'action_controller/abstract'
-require 'action_dispatch'
-require 'action_view'
+autoload :Rack, 'action_dispatch'
+autoload :ActionDispatch, 'action_dispatch'
+autoload :ActionView, 'action_view'
+
+# Common ActiveSupport usage in ActionController
+require "active_support/concern"
+require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/load_error'
+require 'active_support/core_ext/module/attr_internal'
+require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/name_error'
+require 'active_support/inflector' \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index a19a236ef7..ca00e66349 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/module/attr_internal'
-
module AbstractController
class Base
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index 0d5161c80e..ea4b59466e 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -1,3 +1,5 @@
+require "active_support/new_callbacks"
+
module AbstractController
module Callbacks
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 6b73f887c1..5efa37fde3 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -8,12 +8,6 @@ module AbstractController
extlib_inheritable_accessor(:_helpers) { Module.new }
end
- # Override AbstractController::Renderer's _action_view to include the
- # helper module for this class into its helpers module.
- def _action_view
- @_action_view ||= super.tap { |av| av.helpers.include(_helpers) }
- end
-
module ClassMethods
# When a class is inherited, wrap its helper module in a new module.
# This ensures that the parent class's module can be changed
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 2ac4e6068a..f021dd8b62 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -6,6 +6,7 @@ module AbstractController
included do
extlib_inheritable_accessor(:_layout_conditions) { Hash.new }
+ _write_layout_method
end
module ClassMethods
@@ -99,7 +100,7 @@ module AbstractController
# the lookup to. By default, layout lookup is limited to the
# formats specified for the current request.
def _layout_for_name(name, details = {:formats => formats})
- name && _find_by_parts(name, details)
+ name && _find_layout(name, details)
end
# Take in the name and details and find a Template.
@@ -111,7 +112,7 @@ module AbstractController
#
# ==== Returns
# Template:: A template object matching the name and details
- def _find_by_parts(name, details)
+ def _find_layout(name, details)
# TODO: Make prefix actually part of details in ViewPath#find_by_parts
prefix = details.key?(:prefix) ? details.delete(:prefix) : "layouts"
view_paths.find_by_parts(name, details, prefix)
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index b960e152e3..fd33bd2ddd 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,4 +1,3 @@
-require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/logger'
module AbstractController
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index 611d3a16ce..41b7d47458 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -17,25 +17,22 @@ module AbstractController
# An instance of a view class. The default view class is ActionView::Base
#
# The view class must have the following methods:
- # initialize[paths, assigns_for_first_render, controller]
- # paths<Array[ViewPath]>:: A list of resolvers to look for templates in
- # controller<AbstractController::Base> A controller
- # _render_partial_from_controller[options]
+ # View.for_controller[controller] Create a new ActionView instance for a
+ # controller
+ # View#_render_partial_from_controller[options]
+ # - responsible for setting options[:_template]
+ # - Returns String with the rendered partial
# options<Hash>:: see _render_partial in ActionView::Base
- # _render_template_from_controller[template, layout, options, partial]
+ # View#_render_template_from_controller[template, layout, options, partial]
+ # - Returns String with the rendered template
# template<ActionView::Template>:: The template to render
# layout<ActionView::Template>:: The layout to render around the template
# options<Hash>:: See _render_template_with_layout in ActionView::Base
# partial<Boolean>:: Whether or not the template to render is a partial
- # _partial:: If a partial, rather than a template, was rendered, return
- # the partial.
- # helpers:: A module containing the helpers to be used in the view. This
- # module should respond_to include.
- # controller:: The controller that initialized the ActionView
#
# Override this method in a to change the default behavior.
def _action_view
- @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
+ @_action_view ||= ActionView::Base.for_controller(self)
end
# Mostly abstracts the fact that calling render twice is a DoubleRenderError.
diff --git a/actionpack/lib/action_controller/base/compatibility.rb b/actionpack/lib/action_controller/base/compatibility.rb
index cd4b72b1c6..13813ffd17 100644
--- a/actionpack/lib/action_controller/base/compatibility.rb
+++ b/actionpack/lib/action_controller/base/compatibility.rb
@@ -114,7 +114,7 @@ module ActionController
super || (respond_to?(:method_missing) && "_handle_method_missing")
end
- def _find_by_parts(name, details)
+ def _find_layout(name, details)
details[:prefix] = nil if name =~ /\blayouts/
super
end
@@ -123,7 +123,7 @@ module ActionController
def _default_layout(details, require_layout = false)
super
rescue ActionView::MissingTemplate
- _find_by_parts(_layout({}), {})
+ _find_layout(_layout({}), {})
nil
end
diff --git a/actionpack/lib/action_controller/base/helpers.rb b/actionpack/lib/action_controller/base/helpers.rb
index 2fa5ea6519..7c52779064 100644
--- a/actionpack/lib/action_controller/base/helpers.rb
+++ b/actionpack/lib/action_controller/base/helpers.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/load_error'
-require 'active_support/core_ext/name_error'
require 'active_support/dependencies'
module ActionController
diff --git a/actionpack/lib/action_controller/base/http.rb b/actionpack/lib/action_controller/base/http.rb
index ec78bc15a8..3efd1b656f 100644
--- a/actionpack/lib/action_controller/base/http.rb
+++ b/actionpack/lib/action_controller/base/http.rb
@@ -1,5 +1,4 @@
require 'action_controller/abstract'
-require 'active_support/core_ext/module/delegation'
module ActionController
# ActionController::Http provides a way to get a valid Rack application from a controller.
diff --git a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
index c6f7de17bd..159d869a54 100644
--- a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
@@ -77,6 +77,7 @@ module ActionController
end
record = extract_record(record_or_hash_or_array)
+ record = record.to_model if record.respond_to?(:to_model)
namespace = extract_namespace(record_or_hash_or_array)
args = case record_or_hash_or_array
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 7634290ea1..e7c64d0942 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -1,3 +1,4 @@
+require 'action_dispatch'
require 'rack/session/abstract/id'
require 'active_support/core_ext/object/conversions'
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 27a06db5bb..70176a0ea4 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -30,12 +30,14 @@ require File.join(File.dirname(__FILE__), "action_pack")
module ActionView
def self.load_all!
- [Base, InlineTemplate, TemplateError]
+ [Context, Base, InlineTemplate, TemplateError]
end
autoload :Base, 'action_view/base'
+ autoload :Context, 'action_view/context'
autoload :Helpers, 'action_view/helpers'
autoload :InlineTemplate, 'action_view/template/inline'
+ autoload :MissingTemplate, 'action_view/base'
autoload :Partials, 'action_view/render/partials'
autoload :Resolver, 'action_view/template/resolver'
autoload :PathSet, 'action_view/paths'
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 45184f58fb..9e696af83b 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -172,8 +172,6 @@ module ActionView #:nodoc:
attr_accessor :controller
attr_internal :captures
- attr_accessor :output_buffer
-
class << self
delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
delegate :logger, :to => 'ActionController::Base', :allow_nil => true
@@ -206,10 +204,7 @@ module ActionView #:nodoc:
delegate :find_by_parts, :to => :view_paths
- module CompiledTemplates #:nodoc:
- # holds compiled template code
- end
- include CompiledTemplates
+ include Context
def self.process_view_paths(value)
ActionView::PathSet.new(Array(value))
@@ -228,6 +223,12 @@ module ActionView #:nodoc:
end
end
+ def self.for_controller(controller)
+ new(controller.class.view_paths, {}, controller).tap do |view|
+ view.helpers.include(controller._helpers) if controller.respond_to?(:_helpers)
+ end
+ end
+
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc:
@formats = formats || [:html]
@assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb
new file mode 100644
index 0000000000..f212fe25eb
--- /dev/null
+++ b/actionpack/lib/action_view/context.rb
@@ -0,0 +1,44 @@
+module ActionView
+ module CompiledTemplates #:nodoc:
+ # holds compiled template code
+ end
+
+ # ActionView contexts are supplied to ActionController
+ # to render template. The default ActionView context
+ # is ActionView::Base.
+ #
+ # In order to work with ActionController, a Context
+ # must implement:
+ #
+ # Context.for_controller[controller] Create a new ActionView instance for a
+ # controller
+ # Context#_render_partial_from_controller[options]
+ # - responsible for setting options[:_template]
+ # - Returns String with the rendered partial
+ # options<Hash>:: see _render_partial in ActionView::Base
+ # Context#_render_template_from_controller[template, layout, options, partial]
+ # - Returns String with the rendered template
+ # template<ActionView::Template>:: The template to render
+ # layout<ActionView::Template>:: The layout to render around the template
+ # options<Hash>:: See _render_template_with_layout in ActionView::Base
+ # partial<Boolean>:: Whether or not the template to render is a partial
+ #
+ # An ActionView context can also mix in ActionView's
+ # helpers. In order to mix in helpers, a context must
+ # implement:
+ #
+ # Context#controller
+ # - Returns an instance of AbstractController
+ #
+ # In any case, a context must mix in ActionView::Context,
+ # which stores compiled template and provides the output
+ # buffer.
+ module Context
+ include CompiledTemplates
+ attr_accessor :output_buffer
+
+ def convert_to_model(object)
+ object.respond_to?(:to_model) ? object.to_model : object
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb
index 97fa2d80e9..652561f7f8 100644
--- a/actionpack/lib/action_view/helpers.rb
+++ b/actionpack/lib/action_view/helpers.rb
@@ -1,6 +1,7 @@
module ActionView #:nodoc:
module Helpers #:nodoc:
- autoload :ActiveRecordHelper, 'action_view/helpers/active_record_helper'
+ autoload :ActiveModelHelper, 'action_view/helpers/active_model_helper'
+ autoload :AjaxHelper, 'action_view/helpers/ajax_helper'
autoload :AssetTagHelper, 'action_view/helpers/asset_tag_helper'
autoload :AtomFeedHelper, 'action_view/helpers/atom_feed_helper'
autoload :BenchmarkHelper, 'action_view/helpers/benchmark_helper'
@@ -31,7 +32,7 @@ module ActionView #:nodoc:
include SanitizeHelper::ClassMethods
end
- include ActiveRecordHelper
+ include ActiveModelHelper
include AssetTagHelper
include AtomFeedHelper
include BenchmarkHelper
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb
index 75cc651968..0f122d9232 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_model_helper.rb
@@ -15,7 +15,7 @@ module ActionView
# method that creates a complete form for all the basic content types of the record (not associations or aggregations, though). This
# is a great way of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.
# In that case, it's better to use the +input+ method and the specialized +form+ methods in link:classes/ActionView/Helpers/FormHelper.html
- module ActiveRecordHelper
+ module ActiveModelHelper
# Returns a default input tag for the type of object returned by the method. For example, if <tt>@post</tt>
# has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World":
#
@@ -77,6 +77,7 @@ module ActionView
# * <tt>:submit_value</tt> - The text of the submit button (default: "Create" if a new record, otherwise "Update").
def form(record_name, options = {})
record = instance_variable_get("@#{record_name}")
+ record = convert_to_model(record)
options = options.symbolize_keys
options[:action] ||= record.new_record? ? "create" : "update"
@@ -121,6 +122,8 @@ module ActionView
end
options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError')
+ object = convert_to_model(object)
+
if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
(errors = obj.errors[method])
content_tag("div",
@@ -179,6 +182,8 @@ module ActionView
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
+ objects.map! {|o| convert_to_model(o) }
+
count = objects.inject(0) {|sum, object| sum + object.errors.count }
unless count.zero?
html = {}
@@ -226,7 +231,14 @@ module ActionView
end
end
- class InstanceTag #:nodoc:
+ module ActiveRecordInstanceTag
+ def object
+ @active_model_object ||= begin
+ object = super
+ object.respond_to?(:to_model) ? object.to_model : object
+ end
+ end
+
def to_tag(options = {})
case column_type
when :string
@@ -248,11 +260,9 @@ module ActionView
end
%w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
- without = "#{meth}_without_error_wrapping"
- define_method "#{meth}_with_error_wrapping" do |*args|
- error_wrapping(send(without, *args))
+ define_method meth do |*|
+ error_wrapping(super)
end
- alias_method_chain meth, :error_wrapping
end
def error_wrapping(html_tag)
@@ -267,5 +277,9 @@ module ActionView
object.send(:column_for_attribute, @method_name).type
end
end
+
+ class InstanceTag
+ include ActiveRecordInstanceTag
+ end
end
end
diff --git a/actionpack/lib/action_view/helpers/ajax_helper.rb b/actionpack/lib/action_view/helpers/ajax_helper.rb
new file mode 100644
index 0000000000..9cc2acc239
--- /dev/null
+++ b/actionpack/lib/action_view/helpers/ajax_helper.rb
@@ -0,0 +1,68 @@
+module ActionView
+ module Helpers
+ module AjaxHelper
+ include UrlHelper
+
+ def link_to_remote(name, url, options = {})
+ html = options.delete(:html) || {}
+
+ update = options.delete(:update)
+ if update.is_a?(Hash)
+ html["data-update-success"] = update[:success]
+ html["data-update-failure"] = update[:failure]
+ else
+ html["data-update-success"] = update
+ end
+
+ html["data-update-position"] = options.delete(:position)
+ html["data-method"] = options.delete(:method)
+ html["data-remote"] = "true"
+
+ html.merge!(options)
+
+ url = url_for(url) if url.is_a?(Hash)
+ link_to(name, url, html)
+ end
+
+ def button_to_remote(name, options = {}, html_options = {})
+ url = options.delete(:url)
+ url = url_for(url) if url.is_a?(Hash)
+
+ html_options.merge!(:type => "button", :value => name,
+ :"data-url" => url)
+
+ tag(:input, html_options)
+ end
+
+ module Rails2Compatibility
+ def set_callbacks(options, html)
+ [:complete, :failure, :success, :interactive, :loaded, :loading].each do |type|
+ html["data-#{type}-code"] = options.delete(type.to_sym)
+ end
+
+ options.each do |option, value|
+ if option.is_a?(Integer)
+ html["data-#{option}-code"] = options.delete(option)
+ end
+ end
+ end
+
+ def link_to_remote(name, url, options = nil)
+ if !options && url.is_a?(Hash) && url.key?(:url)
+ url, options = url.delete(:url), url
+ end
+
+ set_callbacks(options, options[:html] ||= {})
+
+ super
+ end
+
+ def button_to_remote(name, options = {}, html_options = {})
+ set_callbacks(options, html_options)
+ super
+ end
+ end
+
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 6d6d623938..2d1d19d5f3 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -288,6 +288,8 @@ module ActionView
def apply_form_for_options!(object_or_array, options) #:nodoc:
object = object_or_array.is_a?(Array) ? object_or_array.last : object_or_array
+ object = convert_to_model(object)
+
html_options =
if object.respond_to?(:new_record?) && object.new_record?
{ :class => dom_class(object, :new), :id => dom_id(object), :method => :post }
@@ -488,7 +490,7 @@ module ActionView
object_name = ActionController::RecordIdentifier.singular_class_name(object)
end
- builder = options[:builder] || ActionView::Base.default_form_builder
+ builder = options[:builder] || ActionView.default_form_builder
yield builder.new(object_name, object, self, options, block)
end
@@ -626,8 +628,8 @@ module ActionView
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
# assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
- # It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked.
- # Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
+ # It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked.
+ # Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
# while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
#
# ==== Gotcha
@@ -709,7 +711,8 @@ module ActionView
end
end
- class InstanceTag #:nodoc:
+ module InstanceTagMethods #:nodoc:
+ extend ActiveSupport::Concern
include Helpers::TagHelper, Helpers::FormTagHelper
attr_reader :method_name, :object_name
@@ -832,7 +835,7 @@ module ActionView
self.class.value_before_type_cast(object, @method_name)
end
- class << self
+ module ClassMethods
def value(object, method_name)
object.send method_name unless object.nil?
end
@@ -918,6 +921,10 @@ module ActionView
end
end
+ class InstanceTag
+ include InstanceTagMethods
+ end
+
class FormBuilder #:nodoc:
# The methods which wrap a form helper call.
class_inheritable_accessor :field_helpers
@@ -1022,7 +1029,7 @@ module ActionView
def fields_for_with_nested_attributes(association_name, args, block)
name = "#{object_name}[#{association_name}_attributes]"
association = @object.send(association_name)
- explicit_object = args.first if args.first.respond_to?(:new_record?)
+ explicit_object = args.first.to_model if args.first.respond_to?(:to_model)
if association.is_a?(Array)
children = explicit_object ? [explicit_object] : association
@@ -1054,9 +1061,21 @@ module ActionView
end
end
- class << Base
+ class << ActionView
attr_accessor :default_form_builder
end
- Base.default_form_builder = ::ActionView::Helpers::FormBuilder
+ self.default_form_builder = ::ActionView::Helpers::FormBuilder
+
+ # 2.3 compatibility
+ class << Base
+ def default_form_builder=(builder)
+ ActionView.default_form_builder = builder
+ end
+
+ def default_form_builder
+ ActionView.default_form_builder
+ end
+ end
+
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index a80ffe3c20..ccb14d513a 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -259,7 +259,7 @@ module ActionView
_set_locals(object, locals, template, options)
- self._partial = template
+ options[:_template] = template
_render_template(template, locals)
end
@@ -278,7 +278,7 @@ module ActionView
locals = (options[:locals] ||= {})
index, @_partial_path = 0, nil
collection.map do |object|
- template = passed_template || begin
+ options[:_template] = template = passed_template || begin
_partial_path =
ActionController::RecordIdentifier.partial_path(object, controller_path)
template = _pick_partial_template(_partial_path)
@@ -289,8 +289,6 @@ module ActionView
index += 1
- self._partial = template
-
_render_template(template, locals)
end.join(spacer)
end
diff --git a/actionpack/lib/action_view/template/renderable.rb b/actionpack/lib/action_view/template/renderable.rb
index 54857516ab..7687578165 100644
--- a/actionpack/lib/action_view/template/renderable.rb
+++ b/actionpack/lib/action_view/template/renderable.rb
@@ -12,9 +12,9 @@ module ActionView
end
def load!
- names = Base::CompiledTemplates.instance_methods.grep(/#{method_name_without_locals}/)
+ names = CompiledTemplates.instance_methods.grep(/#{method_name_without_locals}/)
names.each do |name|
- Base::CompiledTemplates.class_eval do
+ CompiledTemplates.class_eval do
remove_method(name)
end
end
@@ -56,7 +56,7 @@ module ActionView
def compile(local_assigns)
render_symbol = method_name(local_assigns)
- if !Base::CompiledTemplates.method_defined?(render_symbol) || recompile?
+ if !CompiledTemplates.method_defined?(render_symbol) || recompile?
compile!(render_symbol, local_assigns)
end
end
@@ -74,7 +74,7 @@ module ActionView
end_src
begin
- ActionView::Base::CompiledTemplates.module_eval(source, filename.to_s, 0)
+ ActionView::CompiledTemplates.module_eval(source, filename.to_s, 0)
rescue Exception => e # errors from template code
if logger = defined?(ActionController) && Base.logger
logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}"
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index fac50cd692..4145045e2d 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -75,7 +75,7 @@ module ActionView
end
begin
- ActionView::Base::CompiledTemplates.module_eval(source, identifier, line)
+ ActionView::CompiledTemplates.module_eval(source, identifier, line)
method_name
rescue Exception => e # errors from template code
if logger = (view && view.logger)
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 7355af4192..3f3951509a 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -23,6 +23,7 @@ module ActionView
class TestCase < ActiveSupport::TestCase
include ActionDispatch::Assertions
include ActionController::TestProcess
+ include ActionView::Context
class_inheritable_accessor :helper_class
@@helper_class = nil
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 30e795a7a2..6e71b85645 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -20,6 +20,7 @@ require 'action_controller/testing/process'
require 'action_view/test_case'
require 'action_controller/testing/integration'
require 'active_support/dependencies'
+require 'active_model'
$tags[:new_base] = true
@@ -97,7 +98,7 @@ module ActionController
partials = hax[:partials]
if expected_count = options[:count]
found = partials.detect { |p, _| p.identifier.match(expected_partial) }
- actual_count = found.nil? ? 0 : found.second
+ actual_count = found.nil? ? 0 : found[1]
msg = build_message(message,
"expecting ? to be rendered ? time(s) but rendered ? time(s)",
expected_partial, expected_count, actual_count)
diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
index 2a31f3be44..df50c3dc6f 100644
--- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
+++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
@@ -127,6 +127,7 @@ end
class Game < Struct.new(:name, :id)
extend ActiveModel::Naming
+ include ActiveModel::Conversion
def to_param
id.to_s
end
diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb
index 28bc608d47..44e49ed3f8 100644
--- a/actionpack/test/controller/record_identifier_test.rb
+++ b/actionpack/test/controller/record_identifier_test.rb
@@ -2,6 +2,7 @@ require 'abstract_unit'
class Comment
extend ActiveModel::Naming
+ include ActiveModel::Conversion
attr_reader :id
def save; @id = 1 end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 453a77e7bc..b3321303c0 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -5,6 +5,7 @@ end
class Workshop
extend ActiveModel::Naming
+ include ActiveModel::Conversion
attr_accessor :id, :new_record
def initialize(id, new_record)
diff --git a/actionpack/test/javascript/ajax_test.rb b/actionpack/test/javascript/ajax_test.rb
new file mode 100644
index 0000000000..b67a91dad3
--- /dev/null
+++ b/actionpack/test/javascript/ajax_test.rb
@@ -0,0 +1,115 @@
+require "abstract_unit"
+
+class AjaxTestCase < ActiveSupport::TestCase
+ include ActionView::Helpers::AjaxHelper
+ include ActionView::Helpers::TagHelper
+
+ def assert_html(html, matches)
+ matches.each do |match|
+ assert_match Regexp.new(Regexp.escape(match)), html
+ end
+ end
+
+ def self.assert_callbacks_work(&blk)
+ define_method(:assert_callbacks_work, &blk)
+
+ [:complete, :failure, :success, :interactive, :loaded, :loading, 404].each do |callback|
+ test "#{callback} callback" do
+ markup = assert_callbacks_work(callback)
+ assert_html markup, %W(data-#{callback}-code="undoRequestCompleted\(request\)")
+ end
+ end
+ end
+end
+
+class LinkToRemoteTest < AjaxTestCase
+ def url_for(hash)
+ "/blog/destroy/4"
+ end
+
+ def link(options = {})
+ link_to_remote("Delete this post", "/blog/destroy/3", options)
+ end
+
+ test "with no update" do
+ assert_html link, %w(href="/blog/destroy/3" Delete\ this\ post data-remote="true")
+ end
+
+ test "basic" do
+ assert_html link(:update => "#posts"),
+ %w(data-update-success="#posts")
+ end
+
+ test "using a url hash" do
+ link = link_to_remote("Delete this post", {:controller => :blog}, :update => "#posts")
+ assert_html link, %w(href="/blog/destroy/4" data-update-success="#posts")
+ end
+
+ test "with :html options" do
+ expected = %{<a href="/blog/destroy/3" data-custom="me" data-update-success="#posts">Delete this post</a>}
+ assert_equal expected, link(:update => "#posts", :html => {"data-custom" => "me"})
+ end
+
+ test "with a hash for :update" do
+ link = link(:update => {:success => "#posts", :failure => "#error"})
+ assert_match /data-update-success="#posts"/, link
+ assert_match /data-update-failure="#error"/, link
+ end
+
+ test "with positional parameters" do
+ link = link(:position => :top, :update => "#posts")
+ assert_match /data\-update\-position="top"/, link
+ end
+
+ test "with an optional method" do
+ link = link(:method => "delete")
+ assert_match /data-method="delete"/, link
+ end
+
+ class LegacyLinkToRemoteTest < AjaxTestCase
+ include ActionView::Helpers::AjaxHelper::Rails2Compatibility
+
+ def link(options)
+ link_to_remote("Delete this post", "/blog/destroy/3", options)
+ end
+
+ test "basic link_to_remote with :url =>" do
+ expected = %{<a href="/blog/destroy/3" data-update-success="#posts">Delete this post</a>}
+ assert_equal expected,
+ link_to_remote("Delete this post", :url => "/blog/destroy/3", :update => "#posts")
+ end
+
+ assert_callbacks_work do |callback|
+ link(callback => "undoRequestCompleted(request)")
+ end
+ end
+end
+
+class ButtonToRemoteTest < AjaxTestCase
+ def button(options, html = {})
+ button_to_remote("Remote outpost", options, html)
+ end
+
+ def url_for(*)
+ "/whatnot"
+ end
+
+ class StandardTest < ButtonToRemoteTest
+ test "basic" do
+ button = button({:url => {:action => "whatnot"}}, {:class => "fine"})
+ [/input/, /class="fine"/, /type="button"/, /value="Remote outpost"/,
+ /data-url="\/whatnot"/].each do |match|
+ assert_match match, button
+ end
+ end
+ end
+
+ class LegacyButtonToRemoteTest < ButtonToRemoteTest
+ include ActionView::Helpers::AjaxHelper::Rails2Compatibility
+
+ assert_callbacks_work do |callback|
+ button(callback => "undoRequestCompleted(request)")
+ end
+ end
+
+end \ No newline at end of file
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
index 9e6f14d373..c6726432ec 100644
--- a/actionpack/test/lib/controller/fake_models.rb
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -2,6 +2,7 @@ require "active_model"
class Customer < Struct.new(:name, :id)
extend ActiveModel::Naming
+ include ActiveModel::Conversion
def to_param
id.to_s
@@ -17,6 +18,7 @@ end
module Quiz
class Question < Struct.new(:name, :id)
extend ActiveModel::Naming
+ include ActiveModel::Conversion
def to_param
id.to_s
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index 9d04c882c8..63032e4e5c 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -1,7 +1,8 @@
require 'abstract_unit'
class ActiveRecordHelperI18nTest < Test::Unit::TestCase
- include ActionView::Helpers::ActiveRecordHelper
+ include ActionView::Context
+ include ActionView::Helpers::ActiveModelHelper
attr_reader :request
diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb
index e1be048838..b07ce6cf5d 100644
--- a/actionpack/test/template/active_record_helper_test.rb
+++ b/actionpack/test/template/active_record_helper_test.rb
@@ -1,22 +1,23 @@
require 'abstract_unit'
class ActiveRecordHelperTest < ActionView::TestCase
- tests ActionView::Helpers::ActiveRecordHelper
+ tests ActionView::Helpers::ActiveModelHelper
silence_warnings do
- Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on)
- Post.class_eval do
- alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
- alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
- alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
+ class Post < Struct.new(:title, :author_name, :body, :secret, :written_on)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
end
- User = Struct.new("User", :email)
- User.class_eval do
- alias_method :email_before_type_cast, :email unless respond_to?(:email_before_type_cast)
+ class User < Struct.new(:email)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
end
- Column = Struct.new("Column", :type, :name, :human_name)
+ class Column < Struct.new(:type, :name, :human_name)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+ end
end
class DirtyPost
diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb
index 6f1179f359..3acaecd142 100644
--- a/actionpack/test/template/atom_feed_helper_test.rb
+++ b/actionpack/test/template/atom_feed_helper_test.rb
@@ -1,7 +1,13 @@
require 'abstract_unit'
-Scroll = Struct.new(:id, :to_param, :title, :body, :updated_at, :created_at)
-Scroll.extend ActiveModel::Naming
+class Scroll < Struct.new(:id, :to_param, :title, :body, :updated_at, :created_at)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
+ def new_record?
+ true
+ end
+end
class ScrollsController < ActionController::Base
FEEDS = {}
diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb
index 9c268aef27..7734e6da73 100644
--- a/actionpack/test/template/compiled_templates_test.rb
+++ b/actionpack/test/template/compiled_templates_test.rb
@@ -3,7 +3,7 @@ require 'controller/fake_models'
class CompiledTemplatesTest < Test::Unit::TestCase
def setup
- @compiled_templates = ActionView::Base::CompiledTemplates
+ @compiled_templates = ActionView::CompiledTemplates
@compiled_templates.instance_methods.each do |m|
@compiled_templates.send(:remove_method, m) if m =~ /^_render_template_/
end
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 515f73c339..99160dd8b1 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1,11 +1,10 @@
require 'abstract_unit'
silence_warnings do
- Post = Struct.new(:title, :author_name, :body, :secret, :written_on, :cost)
- Post.class_eval do
- alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
- alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
- alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
+ class Post < Struct.new(:title, :author_name, :body, :secret, :written_on, :cost)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
alias_method :secret?, :secret
def new_record=(boolean)
@@ -27,6 +26,9 @@ silence_warnings do
end
class Comment
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
attr_reader :id
attr_reader :post_id
def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end
@@ -43,6 +45,9 @@ silence_warnings do
end
class Tag
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
attr_reader :id
attr_reader :post_id
def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end
@@ -59,6 +64,9 @@ silence_warnings do
end
class CommentRelevance
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
attr_reader :id
attr_reader :comment_id
def initialize(id = nil, comment_id = nil); @id, @comment_id = id, comment_id end
@@ -71,6 +79,9 @@ silence_warnings do
end
class TagRelevance
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
attr_reader :id
attr_reader :tag_id
def initialize(id = nil, tag_id = nil); @id, @tag_id = id, tag_id end
@@ -1024,8 +1035,8 @@ class FormHelperTest < ActionView::TestCase
end
def test_default_form_builder
- old_default_form_builder, ActionView::Base.default_form_builder =
- ActionView::Base.default_form_builder, LabelledFormBuilder
+ old_default_form_builder, ActionView.default_form_builder =
+ ActionView.default_form_builder, LabelledFormBuilder
form_for(:post, @post) do |f|
concat f.text_field(:title)
@@ -1042,7 +1053,7 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
ensure
- ActionView::Base.default_form_builder = old_default_form_builder
+ ActionView.default_form_builder = old_default_form_builder
end
def test_default_form_builder_with_active_record_helpers
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index a7a1bc99f3..acbf311212 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -1,10 +1,15 @@
require 'abstract_unit'
+require 'active_model'
-Bunny = Struct.new(:Bunny, :id)
-Bunny.extend ActiveModel::Naming
+class Bunny < Struct.new(:Bunny, :id)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+end
class Author
extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
attr_reader :id
def save; @id = 1 end
def new_record?; @id.nil? end
@@ -15,6 +20,7 @@ end
class Article
extend ActiveModel::Naming
+ include ActiveModel::Conversion
attr_reader :id
attr_reader :author_id
def save; @id = 1; @author_id = 1 end
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 5b840d123b..4144fea678 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -2,11 +2,12 @@ require 'abstract_unit'
class Post
extend ActiveModel::Naming
+ include ActiveModel::Conversion
def id
45
end
def body
- "What a wonderful world!"
+ super || "What a wonderful world!"
end
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index f0364fd660..9eeb26831c 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -495,6 +495,7 @@ end
class Workshop
extend ActiveModel::Naming
+ include ActiveModel::Conversion
attr_accessor :id, :new_record
def initialize(id, new_record)
@@ -512,6 +513,7 @@ end
class Session
extend ActiveModel::Naming
+ include ActiveModel::Conversion
attr_accessor :id, :workshop_id, :new_record
def initialize(id, new_record)