From b0429f5e66b4e33f9d0ba7b066a3dbfdab68534c Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 11 Jul 2009 23:39:45 -0400 Subject: Rename method to a more obvious name --- actionpack/lib/action_controller/abstract/layouts.rb | 4 ++-- actionpack/lib/action_controller/base/compatibility.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb index 2ac4e6068a..d8276cfa83 100644 --- a/actionpack/lib/action_controller/abstract/layouts.rb +++ b/actionpack/lib/action_controller/abstract/layouts.rb @@ -99,7 +99,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 +111,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/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 -- cgit v1.2.3 From 28508d444e36dc8b5819f011f0a2398f44d8d3e3 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 15 Jul 2009 14:15:52 -0700 Subject: Centralize commonly used parts of AS in ActionController into action_controller.rb --- actionpack/lib/action_controller.rb | 16 +++++++++++++--- actionpack/lib/action_controller/abstract/base.rb | 2 -- actionpack/lib/action_controller/abstract/callbacks.rb | 2 ++ actionpack/lib/action_controller/abstract/logger.rb | 1 - actionpack/lib/action_controller/base/helpers.rb | 2 -- actionpack/lib/action_controller/base/http.rb | 1 - 6 files changed, 15 insertions(+), 9 deletions(-) (limited to 'actionpack/lib') 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/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/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. -- cgit v1.2.3 From 1273ffa1861d15eb7518b7bfab6003bb3d9ca347 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 15 Jul 2009 14:16:12 -0700 Subject: Fix AbstractController::Layouts to work when included directly on a controller --- actionpack/lib/action_controller/abstract/layouts.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb index d8276cfa83..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 -- cgit v1.2.3 From 1a2946a6d9b1dbcf3a4c77654693d73f9b11bde1 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 15 Jul 2009 14:16:30 -0700 Subject: Add some missing dependencies --- actionpack/lib/action_controller/testing/process.rb | 1 + actionpack/lib/action_view.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'actionpack/lib') 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..2a17faf99a 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -36,6 +36,7 @@ module ActionView autoload :Base, 'action_view/base' 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' -- cgit v1.2.3 From bb530923bcd5c643f9bfca8e36cd3fa36365032d Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 19 Jul 2009 21:53:02 +0900 Subject: Simplify required "ActionView compliant" API --- actionpack/lib/action_controller/abstract/helpers.rb | 6 ------ actionpack/lib/action_controller/abstract/renderer.rb | 19 ++++++++----------- actionpack/lib/action_view/base.rb | 6 ++++++ actionpack/lib/action_view/render/partials.rb | 6 ++---- 4 files changed, 16 insertions(+), 21 deletions(-) (limited to 'actionpack/lib') 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/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:: A list of resolvers to look for templates in - # controller 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:: 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:: The template to render # layout:: The layout to render around the template # options:: See _render_template_with_layout in ActionView::Base # partial:: 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_view/base.rb b/actionpack/lib/action_view/base.rb index 45184f58fb..5915337dd2 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -228,6 +228,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/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 -- cgit v1.2.3 From 0f2914be405410e824b40dcff28e5dfa541bdb2a Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 19 Jul 2009 22:12:15 +0900 Subject: Separate ActionView::Context so something else can easily be made into an AV context --- actionpack/lib/action_view.rb | 3 +- actionpack/lib/action_view/base.rb | 7 +--- actionpack/lib/action_view/context.rb | 40 +++++++++++++++++++++++ actionpack/lib/action_view/template/renderable.rb | 8 ++--- actionpack/lib/action_view/template/template.rb | 2 +- 5 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 actionpack/lib/action_view/context.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 2a17faf99a..70176a0ea4 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -30,10 +30,11 @@ 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' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 5915337dd2..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)) diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb new file mode 100644 index 0000000000..63651fa3f1 --- /dev/null +++ b/actionpack/lib/action_view/context.rb @@ -0,0 +1,40 @@ +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:: see _render_partial in ActionView::Base + # Context#_render_template_from_controller[template, layout, options, partial] + # - Returns String with the rendered template + # template:: The template to render + # layout:: The layout to render around the template + # options:: See _render_template_with_layout in ActionView::Base + # partial:: 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 + end +end \ No newline at end of file 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) -- cgit v1.2.3 From b20d68446d2fe98d129385a17a3a4cdacd4b5025 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 19 Jul 2009 22:30:00 +0900 Subject: Move default_form_builder to ActionView so it'll work in environments not using ActionView::Base --- actionpack/lib/action_view/helpers/form_helper.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 6d6d623938..a74709e98a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -488,7 +488,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 @@ -1054,9 +1054,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 -- cgit v1.2.3 From 5ffaaa71d149c9807260c950c9a61d01fe734827 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 00:27:04 +0900 Subject: Define ActiveModel API Compliance - Define to_model on AR - Define to_model on ActiveModel::APICompliant - Update test fixtures to be API Compliant - Start using to_model in AP --- .../routing/generation/polymorphic_routes.rb | 1 + .../action_view/helpers/active_record_helper.rb | 24 +++++++++++++++++----- actionpack/lib/action_view/helpers/form_helper.rb | 13 ++++++++---- 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'actionpack/lib') 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_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 75cc651968..8dffd3bc91 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -77,6 +77,7 @@ module ActionView # * :submit_value - 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 = record.to_model if record.respond_to?(:to_model) 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 = object.to_model if object.respond_to?(:to_model) + 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| o.respond_to?(:to_model) ? o.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/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index a74709e98a..ecbdcd8e7a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -626,8 +626,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 +709,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 +833,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 +919,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 -- cgit v1.2.3 From 13e18dd94000cef2b2058b96d62de16b7d3a2200 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 00:58:59 +0900 Subject: Update some tests and add a to_model to form helpers --- actionpack/lib/action_view/context.rb | 8 ++++++-- actionpack/lib/action_view/helpers/active_record_helper.rb | 6 +++--- actionpack/lib/action_view/helpers/form_helper.rb | 2 ++ actionpack/lib/action_view/test_case.rb | 1 + 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb index 63651fa3f1..f212fe25eb 100644 --- a/actionpack/lib/action_view/context.rb +++ b/actionpack/lib/action_view/context.rb @@ -2,7 +2,7 @@ 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. @@ -10,7 +10,7 @@ module ActionView # In order to work with ActionController, a Context # must implement: # - # Context.for_controller[controller] Create a new ActionView instance for a + # Context.for_controller[controller] Create a new ActionView instance for a # controller # Context#_render_partial_from_controller[options] # - responsible for setting options[:_template] @@ -36,5 +36,9 @@ module ActionView 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/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 8dffd3bc91..409b27de73 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -77,7 +77,7 @@ module ActionView # * :submit_value - 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 = record.to_model if record.respond_to?(:to_model) + record = convert_to_model(record) options = options.symbolize_keys options[:action] ||= record.new_record? ? "create" : "update" @@ -122,7 +122,7 @@ module ActionView end options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError') - object = object.to_model if object.respond_to?(:to_model) + object = convert_to_model(object) if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && (errors = obj.errors[method]) @@ -182,7 +182,7 @@ module ActionView objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact end - objects.map! {|o| o.respond_to?(:to_model) ? o.to_model : o } + objects.map! {|o| convert_to_model(o) } count = objects.inject(0) {|sum, object| sum + object.errors.count } unless count.zero? diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index ecbdcd8e7a..56ee43496c 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 } 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 -- cgit v1.2.3 From b00cac4adc0413418ffd2c59b52c8f64acff406b Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 01:22:24 +0900 Subject: Finish convert_to_object updates --- actionpack/lib/action_view/helpers/form_helper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 56ee43496c..2b39d08035 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1029,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 @@ -1044,6 +1044,8 @@ module ActionView end def fields_for_nested_model(name, object, args, block) + object = convert_to_model(object) + if object.new_record? @template.fields_for(name, object, *args, &block) else -- cgit v1.2.3 From f2f5cdc8bcd9df3a297ea02b80dbdb21790de732 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 01:28:15 +0900 Subject: Rename ActiveRecordHelper to ActiveModelHelper --- actionpack/lib/action_view/helpers.rb | 4 +- .../lib/action_view/helpers/active_model_helper.rb | 285 +++++++++++++++++++++ .../action_view/helpers/active_record_helper.rb | 285 --------------------- actionpack/lib/action_view/helpers/form_helper.rb | 2 - 4 files changed, 287 insertions(+), 289 deletions(-) create mode 100644 actionpack/lib/action_view/helpers/active_model_helper.rb delete mode 100644 actionpack/lib/action_view/helpers/active_record_helper.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index 97fa2d80e9..c1c0eb59ae 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -1,6 +1,6 @@ module ActionView #:nodoc: module Helpers #:nodoc: - autoload :ActiveRecordHelper, 'action_view/helpers/active_record_helper' + autoload :ActiveModelHelper, 'action_view/helpers/active_model_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 +31,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_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb new file mode 100644 index 0000000000..0f122d9232 --- /dev/null +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -0,0 +1,285 @@ +require 'cgi' +require 'action_view/helpers/form_helper' +require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/enumerable' +require 'active_support/core_ext/kernel/reporting' + +module ActionView + class Base + @@field_error_proc = Proc.new{ |html_tag, instance| "
#{html_tag}
" } + cattr_accessor :field_error_proc + end + + module Helpers + # The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the +form+ + # 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 ActiveModelHelper + # Returns a default input tag for the type of object returned by the method. For example, if @post + # has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World": + # + # input("post", "title") + # # => + def input(record_name, method, options = {}) + InstanceTag.new(record_name, method, self).to_tag(options) + end + + # Returns an entire form with all needed input tags for a specified Active Record object. For example, if @post + # has attributes named +title+ of type +VARCHAR+ and +body+ of type +TEXT+ then + # + # form("post") + # + # would yield a form like the following (modulus formatting): + # + #
+ #

+ #
+ # + #

+ #

+ #
+ # + #

+ # + #
+ # + # It's possible to specialize the form builder by using a different action name and by supplying another + # block renderer. For example, if @entry has an attribute +message+ of type +VARCHAR+ then + # + # form("entry", + # :action => "sign", + # :input_block => Proc.new { |record, column| + # "#{column.human_name}: #{input(record, column.name)}
" + # }) + # + # would yield a form like the following (modulus formatting): + # + #
+ # Message: + #
+ # + #
+ # + # It's also possible to add additional content to the form by giving it a block, such as: + # + # form("entry", :action => "sign") do |form| + # form << content_tag("b", "Department") + # form << collection_select("department", "id", @departments, "id", "name") + # end + # + # The following options are available: + # + # * :action - The action used when submitting the form (default: +create+ if a new record, otherwise +update+). + # * :input_block - Specialize the output using a different block, see above. + # * :method - The method used when submitting the form (default: +post+). + # * :multipart - Whether to change the enctype of the form to "multipart/form-data", used when uploading a file (default: +false+). + # * :submit_value - 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" + action = url_for(:action => options[:action], :id => record) + + submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize + + contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil) + contents << hidden_field(record_name, :id) unless record.new_record? + contents << all_input_tags(record, record_name, options) + yield contents if block_given? + contents << submit_tag(submit_value) + contents << '' + end + + # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. + # This error message is wrapped in a DIV tag, which can be extended to include a :prepend_text + # and/or :append_text (to properly explain the error), and a :css_class to style it + # accordingly. +object+ should either be the name of an instance variable or the actual object. The method can be + # passed in either as a string or a symbol. + # As an example, let's say you have a model @post that has an error message on the +title+ attribute: + # + # <%= error_message_on "post", "title" %> + # # =>
can't be empty
+ # + # <%= error_message_on @post, :title %> + # # =>
can't be empty
+ # + # <%= error_message_on "post", "title", + # :prepend_text => "Title simply ", + # :append_text => " (or it won't work).", + # :css_class => "inputError" %> + def error_message_on(object, method, *args) + options = args.extract_options! + unless args.empty? + ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' + + 'prepend_text, append_text, and css_class arguments', caller) + + options[:prepend_text] = args[0] || '' + options[:append_text] = args[1] || '' + options[:css_class] = args[2] || 'formError' + 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", + "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.first)}#{options[:append_text]}", + :class => options[:css_class] + ) + else + '' + end + end + + # Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names + # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are + # provided. + # + # This DIV can be tailored by the following options: + # + # * :header_tag - Used for the header of the error div (default: "h2"). + # * :id - The id of the error div (default: "errorExplanation"). + # * :class - The class of the error div (default: "errorExplanation"). + # * :object - The object (or array of objects) for which to display errors, + # if you need to escape the instance variable convention. + # * :object_name - The object name to use in the header, or any text that you prefer. + # If :object_name is not set, the name of the first object will be used. + # * :header_message - The message in the header of the error div. Pass +nil+ + # or an empty string to avoid the header message altogether. (Default: "X errors + # prohibited this object from being saved"). + # * :message - The explanation message after the header message and before + # the error list. Pass +nil+ or an empty string to avoid the explanation message + # altogether. (Default: "There were problems with the following fields:"). + # + # To specify the display for one object, you simply provide its name as a parameter. + # For example, for the @user model: + # + # error_messages_for 'user' + # + # To specify more than one object, you simply list them; optionally, you can add an extra :object_name parameter, which + # will be the name used in the header message: + # + # error_messages_for 'user_common', 'user', :object_name => 'user' + # + # If the objects cannot be located as instance variables, you can add an extra :object parameter which gives the actual + # object (or array of objects to use): + # + # error_messages_for 'user', :object => @question.user + # + # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what + # you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors + # instance yourself and set it up. View the source of this method to see how easy it is. + def error_messages_for(*params) + options = params.extract_options!.symbolize_keys + + if object = options.delete(:object) + objects = [object].flatten + else + 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 = {} + [:id, :class].each do |key| + if options.include?(key) + value = options[key] + html[key] = value unless value.blank? + else + html[key] = 'errorExplanation' + end + end + options[:object_name] ||= params.first + + I18n.with_options :locale => options[:locale], :scope => [:activerecord, :errors, :template] do |locale| + header_message = if options.include?(:header_message) + options[:header_message] + else + object_name = options[:object_name].to_s.gsub('_', ' ') + object_name = I18n.t(options[:object_name].to_s, :default => object_name, :scope => [:activerecord, :models], :count => 1) + locale.t :header, :count => count, :model => object_name + end + message = options.include?(:message) ? options[:message] : locale.t(:body) + error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, ERB::Util.html_escape(msg)) } }.join + + contents = '' + contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank? + contents << content_tag(:p, message) unless message.blank? + contents << content_tag(:ul, error_messages) + + content_tag(:div, contents, html) + end + else + '' + end + end + + private + def all_input_tags(record, record_name, options) + input_block = options[:input_block] || default_input_block + record.class.content_columns.collect{ |column| input_block.call(record_name, column) }.join("\n") + end + + def default_input_block + Proc.new { |record, column| %(


#{input(record, column.name)}

) } + end + end + + 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 + field_type = @method_name.include?("password") ? "password" : "text" + to_input_field_tag(field_type, options) + when :text + to_text_area_tag(options) + when :integer, :float, :decimal + to_input_field_tag("text", options) + when :date + to_date_select_tag(options) + when :datetime, :timestamp + to_datetime_select_tag(options) + when :time + to_time_select_tag(options) + when :boolean + to_boolean_select_tag(options) + end + end + + %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth| + define_method meth do |*| + error_wrapping(super) + end + end + + def error_wrapping(html_tag) + if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any? + Base.field_error_proc.call(html_tag, self) + else + html_tag + end + end + + def column_type + 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/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb deleted file mode 100644 index 409b27de73..0000000000 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ /dev/null @@ -1,285 +0,0 @@ -require 'cgi' -require 'action_view/helpers/form_helper' -require 'active_support/core_ext/class/attribute_accessors' -require 'active_support/core_ext/enumerable' -require 'active_support/core_ext/kernel/reporting' - -module ActionView - class Base - @@field_error_proc = Proc.new{ |html_tag, instance| "
#{html_tag}
" } - cattr_accessor :field_error_proc - end - - module Helpers - # The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the +form+ - # 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 - # Returns a default input tag for the type of object returned by the method. For example, if @post - # has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World": - # - # input("post", "title") - # # => - def input(record_name, method, options = {}) - InstanceTag.new(record_name, method, self).to_tag(options) - end - - # Returns an entire form with all needed input tags for a specified Active Record object. For example, if @post - # has attributes named +title+ of type +VARCHAR+ and +body+ of type +TEXT+ then - # - # form("post") - # - # would yield a form like the following (modulus formatting): - # - #
- #

- #
- # - #

- #

- #
- # - #

- # - #
- # - # It's possible to specialize the form builder by using a different action name and by supplying another - # block renderer. For example, if @entry has an attribute +message+ of type +VARCHAR+ then - # - # form("entry", - # :action => "sign", - # :input_block => Proc.new { |record, column| - # "#{column.human_name}: #{input(record, column.name)}
" - # }) - # - # would yield a form like the following (modulus formatting): - # - #
- # Message: - #
- # - #
- # - # It's also possible to add additional content to the form by giving it a block, such as: - # - # form("entry", :action => "sign") do |form| - # form << content_tag("b", "Department") - # form << collection_select("department", "id", @departments, "id", "name") - # end - # - # The following options are available: - # - # * :action - The action used when submitting the form (default: +create+ if a new record, otherwise +update+). - # * :input_block - Specialize the output using a different block, see above. - # * :method - The method used when submitting the form (default: +post+). - # * :multipart - Whether to change the enctype of the form to "multipart/form-data", used when uploading a file (default: +false+). - # * :submit_value - 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" - action = url_for(:action => options[:action], :id => record) - - submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize - - contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil) - contents << hidden_field(record_name, :id) unless record.new_record? - contents << all_input_tags(record, record_name, options) - yield contents if block_given? - contents << submit_tag(submit_value) - contents << '' - end - - # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. - # This error message is wrapped in a DIV tag, which can be extended to include a :prepend_text - # and/or :append_text (to properly explain the error), and a :css_class to style it - # accordingly. +object+ should either be the name of an instance variable or the actual object. The method can be - # passed in either as a string or a symbol. - # As an example, let's say you have a model @post that has an error message on the +title+ attribute: - # - # <%= error_message_on "post", "title" %> - # # =>
can't be empty
- # - # <%= error_message_on @post, :title %> - # # =>
can't be empty
- # - # <%= error_message_on "post", "title", - # :prepend_text => "Title simply ", - # :append_text => " (or it won't work).", - # :css_class => "inputError" %> - def error_message_on(object, method, *args) - options = args.extract_options! - unless args.empty? - ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' + - 'prepend_text, append_text, and css_class arguments', caller) - - options[:prepend_text] = args[0] || '' - options[:append_text] = args[1] || '' - options[:css_class] = args[2] || 'formError' - 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", - "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.first)}#{options[:append_text]}", - :class => options[:css_class] - ) - else - '' - end - end - - # Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names - # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are - # provided. - # - # This DIV can be tailored by the following options: - # - # * :header_tag - Used for the header of the error div (default: "h2"). - # * :id - The id of the error div (default: "errorExplanation"). - # * :class - The class of the error div (default: "errorExplanation"). - # * :object - The object (or array of objects) for which to display errors, - # if you need to escape the instance variable convention. - # * :object_name - The object name to use in the header, or any text that you prefer. - # If :object_name is not set, the name of the first object will be used. - # * :header_message - The message in the header of the error div. Pass +nil+ - # or an empty string to avoid the header message altogether. (Default: "X errors - # prohibited this object from being saved"). - # * :message - The explanation message after the header message and before - # the error list. Pass +nil+ or an empty string to avoid the explanation message - # altogether. (Default: "There were problems with the following fields:"). - # - # To specify the display for one object, you simply provide its name as a parameter. - # For example, for the @user model: - # - # error_messages_for 'user' - # - # To specify more than one object, you simply list them; optionally, you can add an extra :object_name parameter, which - # will be the name used in the header message: - # - # error_messages_for 'user_common', 'user', :object_name => 'user' - # - # If the objects cannot be located as instance variables, you can add an extra :object parameter which gives the actual - # object (or array of objects to use): - # - # error_messages_for 'user', :object => @question.user - # - # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what - # you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors - # instance yourself and set it up. View the source of this method to see how easy it is. - def error_messages_for(*params) - options = params.extract_options!.symbolize_keys - - if object = options.delete(:object) - objects = [object].flatten - else - 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 = {} - [:id, :class].each do |key| - if options.include?(key) - value = options[key] - html[key] = value unless value.blank? - else - html[key] = 'errorExplanation' - end - end - options[:object_name] ||= params.first - - I18n.with_options :locale => options[:locale], :scope => [:activerecord, :errors, :template] do |locale| - header_message = if options.include?(:header_message) - options[:header_message] - else - object_name = options[:object_name].to_s.gsub('_', ' ') - object_name = I18n.t(options[:object_name].to_s, :default => object_name, :scope => [:activerecord, :models], :count => 1) - locale.t :header, :count => count, :model => object_name - end - message = options.include?(:message) ? options[:message] : locale.t(:body) - error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, ERB::Util.html_escape(msg)) } }.join - - contents = '' - contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank? - contents << content_tag(:p, message) unless message.blank? - contents << content_tag(:ul, error_messages) - - content_tag(:div, contents, html) - end - else - '' - end - end - - private - def all_input_tags(record, record_name, options) - input_block = options[:input_block] || default_input_block - record.class.content_columns.collect{ |column| input_block.call(record_name, column) }.join("\n") - end - - def default_input_block - Proc.new { |record, column| %(


#{input(record, column.name)}

) } - end - end - - 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 - field_type = @method_name.include?("password") ? "password" : "text" - to_input_field_tag(field_type, options) - when :text - to_text_area_tag(options) - when :integer, :float, :decimal - to_input_field_tag("text", options) - when :date - to_date_select_tag(options) - when :datetime, :timestamp - to_datetime_select_tag(options) - when :time - to_time_select_tag(options) - when :boolean - to_boolean_select_tag(options) - end - end - - %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth| - define_method meth do |*| - error_wrapping(super) - end - end - - def error_wrapping(html_tag) - if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any? - Base.field_error_proc.call(html_tag, self) - else - html_tag - end - end - - def column_type - 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/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 2b39d08035..2d1d19d5f3 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1044,8 +1044,6 @@ module ActionView end def fields_for_nested_model(name, object, args, block) - object = convert_to_model(object) - if object.new_record? @template.fields_for(name, object, *args, &block) else -- cgit v1.2.3 From d80316ad3269e11c2be9be0727ae518f5e427d24 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 16:13:21 -0700 Subject: First effort at new Ajax helpers --- actionpack/lib/action_view/helpers.rb | 1 + actionpack/lib/action_view/helpers/ajax_helper.rb | 68 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 actionpack/lib/action_view/helpers/ajax_helper.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index c1c0eb59ae..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 :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' 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 -- cgit v1.2.3