Skip to content

Commit

Permalink
Applied Yehuda's patch; Sharing extract_object_name_for_form! between…
Browse files Browse the repository at this point in the history
… form_helper and ajax_helper; Added script_decorator helper
  • Loading branch information
foobarfighter authored and stefanpenner committed Jan 27, 2010
1 parent c1ce17a commit 5ced122
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 59 deletions.
52 changes: 28 additions & 24 deletions actionpack/lib/action_view/helpers/ajax_helper.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ module Helpers
module AjaxHelper module AjaxHelper
include UrlHelper include UrlHelper


def remote_form_for(record_or_name_or_array, *args, &proc)
options = args.extract_options!
object_name = extract_object_name_for_form!(args, options, record_or_name_or_array)

concat(form_remote_tag(options))
fields_for(object_name, *(args << options), &proc)
concat('</form>'.html_safe!)
end
alias_method :form_remote_for, :remote_form_for

def form_remote_tag(options = {}, &block) def form_remote_tag(options = {}, &block)
attributes = {} attributes = {}
attributes.merge!(extract_remote_attributes!(options)) attributes.merge!(extract_remote_attributes!(options))
Expand Down Expand Up @@ -50,41 +60,35 @@ def button_to_remote(name, options = {}, html_options = {})
end end


def observe_field(name, options = {}) def observe_field(name, options = {})
if options[:url] url = options[:url]
options[:url] = options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url] options[:url] = url_for(url) if url && url.is_a?(Hash)
end


if options[:frequency] frequency = options.delete(:frequency)
case options[:frequency] if frequency && frequency != 0
when 0 options[:frequency] = frequency.to_i
options.delete(:frequency)
else
options[:frequency] = options[:frequency].to_i
end
end end


if options[:with] if with = options[:with]
if options[:with] !~ /[\{=(.]/ if with !~ /[\{=(.]/
options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)" options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)"
else else
options[:with] ||= 'value' unless options[:function] options[:with] ||= 'value' unless options[:function]
end end
end end


if options[:function] if function = options[:function]
statements = options[:function] # || remote_function(options) # TODO: Need to implement remote function - BR statements = function # || remote_function(options) # TODO: Need to implement remote function - BR
options[:function] = JSFunction.new(statements, "element", "value") options[:function] = JSFunction.new(statements, "element", "value")
end end

options[:name] = name options[:name] = name


<<-SCRIPT script_decorator("field_observer", options)
<script type="application/json" data-js-type="field_observer"> end
//<![CDATA[
#{options.to_json} def script_decorator(js_type, options)
// ]]> attributes = [%(type="application/json"), %(data-js-type="#{js_type}")]
</script> attributes += options.map{|k, v| %(data-#{k}="#{v}")}
SCRIPT "<script " + attributes.join(" ") + "></script>"
end end


module Rails2Compatibility module Rails2Compatibility
Expand Down Expand Up @@ -124,11 +128,11 @@ def initialize(statements, *arguments)
@statements, @arguments = statements, arguments @statements, @arguments = statements, arguments
end end


def as_json(options = nil) def to_s(options = nil)
"function(#{@arguments.join(", ")}) {#{@statements}}" "function(#{@arguments.join(", ")}) {#{@statements}}"
end end
end end


end end
end end
end end
36 changes: 20 additions & 16 deletions actionpack/lib/action_view/helpers/form_helper.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -262,23 +262,8 @@ module FormHelper
# FormTagHelper#form_tag. # FormTagHelper#form_tag.
def form_for(record_or_name_or_array, *args, &proc) def form_for(record_or_name_or_array, *args, &proc)
raise ArgumentError, "Missing block" unless block_given? raise ArgumentError, "Missing block" unless block_given?

options = args.extract_options! options = args.extract_options!

object_name = extract_object_name_for_form!(args, options, record_or_name_or_array)
case record_or_name_or_array
when String, Symbol
object_name = record_or_name_or_array
when Array
object = record_or_name_or_array.last
object_name = ActionController::RecordIdentifier.singular_class_name(object)
apply_form_for_options!(record_or_name_or_array, options)
args.unshift object
else
object = record_or_name_or_array
object_name = ActionController::RecordIdentifier.singular_class_name(object)
apply_form_for_options!([object], options)
args.unshift object
end


concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {})) concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
fields_for(object_name, *(args << options), &proc) fields_for(object_name, *(args << options), &proc)
Expand Down Expand Up @@ -742,6 +727,25 @@ def check_box(object_name, method, options = {}, checked_value = "1", unchecked_
def radio_button(object_name, method, tag_value, options = {}) def radio_button(object_name, method, tag_value, options = {})
InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options) InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options)
end end

private
def extract_object_name_for_form!(args, options, record_or_name_or_array)
case record_or_name_or_array
when String, Symbol
object_name = record_or_name_or_array
when Array
object = record_or_name_or_array.last
object_name = ActionController::RecordIdentifier.singular_class_name(object)
apply_form_for_options!(record_or_name_or_array, options)
args.unshift object
else
object = record_or_name_or_array
object_name = ActionController::RecordIdentifier.singular_class_name(object)
apply_form_for_options!([object], options)
args.unshift object
end
object_name
end
end end


module InstanceTagMethods #:nodoc: module InstanceTagMethods #:nodoc:
Expand Down
50 changes: 31 additions & 19 deletions actionpack/test/javascript/ajax_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -188,15 +188,10 @@ def protect_against_forgery?
end end


test "using a :method option" do test "using a :method option" do
<<<<<<< HEAD
expected_form_attributes = %w(form action="/url/hash" method="post" data-remote="true" data-update-success="#glass_of_beer")
# TODO: Ask Katz: Why does rails do this? Some web servers don't allow PUT or DELETE from what I remember... - BR
=======
expected_form_attributes = %w(form action="/url/hash" method="post" data-js-type="remote" data-update-success="#glass_of_beer") expected_form_attributes = %w(form action="/url/hash" method="post" data-js-type="remote" data-update-success="#glass_of_beer")
# TODO: Experiment with not using this _method param. Apparently this is done to address browser incompatibilities, but since # TODO: Experiment with not using this _method param. Apparently this is done to address browser incompatibilities, but since
# we have a layer between the HTML and the JS libs now, we can probably get away with letting JS the JS libs handle the requirement # we have a layer between the HTML and the JS libs now, we can probably get away with letting JS the JS libs handle the requirement
# for an extra field if needed. # for an extra field if needed.
>>>>>>> 6af9c2f... Changed data-remote='true' to data-js-type='remote'
expected_input_attributes = %w(input name="_method" type="hidden" value="put") expected_input_attributes = %w(input name="_method" type="hidden" value="put")


assert_html form_remote_tag(:update => "#glass_of_beer", :url => { :action => :fast }, :html => { :method => :put }), assert_html form_remote_tag(:update => "#glass_of_beer", :url => { :action => :fast }, :html => { :method => :put }),
Expand Down Expand Up @@ -341,6 +336,20 @@ class LegacyButtonToRemoteTest < ButtonToRemoteTest
button(callback => "undoRequestCompleted(request)") button(callback => "undoRequestCompleted(request)")
end end
end end
<<<<<<< HEAD
=======
end

class ScriptDecoratorTest < AjaxTestCase
def decorator()
script_decorator("foo_type", :foo => "bar", :baz => "bang")
end

test "basic" do
expected = %(<script type="application/json" data-js-type="foo_type" data-foo="bar" data-baz="bang"></script>)
assert_dom_equal expected, decorator
end
>>>>>>> bd54253... Applied Yehuda's patch; Sharing extract_object_name_for_form! between form_helper and ajax_helper; Added script_decorator helper
end end
class ObserveFieldTest < AjaxTestCase class ObserveFieldTest < AjaxTestCase
Expand All @@ -358,18 +367,18 @@ def field(options = {})
end end
test "using a url string" do test "using a url string" do
assert_data_element_json field(:url => "/some/other/url"), assert_html field(:url => "/some/other/url"),
"url" => "/some/other/url", "name" => "title" %w(script data-url="/some/other/url" data-name="title")
end end
test "using a url hash" do test "using a url hash" do
assert_data_element_json field(:url => {:controller => :blog, :action => :update}), assert_html field(:url => {:controller => :blog, :action => :update}),
"url" => "/url/hash", "name" => "title" %w(script data-url="/url/hash" data-name="title")
end end
test "using a :frequency option" do test "using a :frequency option" do
assert_data_element_json field(:url => { :controller => :blog }, :frequency => 5.minutes), assert_html field(:url => { :controller => :blog }, :frequency => 5.minutes),
"url" => "/url/hash", "name" => "title", "frequency" => 300 %w(script data-url="/url/hash" data-name="title" data-frequency="300")
end end
test "using a :frequency option of 0" do test "using a :frequency option of 0" do
Expand All @@ -384,19 +393,22 @@ def field(options = {})
# TODO: Consider using JSON instead of strings. Is using 'value' as a magical reference to the value of the observed field weird? (Rails2 does this) - BR # TODO: Consider using JSON instead of strings. Is using 'value' as a magical reference to the value of the observed field weird? (Rails2 does this) - BR
test "using a :with option" do test "using a :with option" do
assert_data_element_json field(:with => "foo"), assert_html field(:with => "foo"),
"name" => "title", "with" => "'foo=' + encodeURIComponent(value)" %w(script data-name="title" data-with="'foo=' + encodeURIComponent(value)")
assert_data_element_json field(:with => "'foo=' + encodeURIComponent(value)"),
"name" => "title", "with" => "'foo=' + encodeURIComponent(value)" assert_html field(:with => "'foo=' + encodeURIComponent(value)"),
%w(script data-name="title" data-with="'foo=' + encodeURIComponent(value)")
end end
test "using json in a :with option" do test "using json in a :with option" do
assert_data_element_json field(:with => "{'id':value}"), assert_html field(:with => "{'id':value}"),
"name" => "title", "with" => "{'id':value}" %w(script data-name="title" data-with="{'id':value}")
end end
test "using :function for callback" do test "using :function for callback" do
assert_data_element_json field(:function => "alert('Element changed')"), assert_html field(:function => "alert('Element changed')"),
"name" => "title", "function" => "function(element, value) {alert('Element changed')}" %w(script data-function="function(element, value) {alert('Element changed')}")

end end
end end

0 comments on commit 5ced122

Please sign in to comment.