af-client_side_validations 3.1.4.af1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/client_side_validations.gemspec +34 -0
  2. data/lib/client_side_validations/action_view/form_builder.rb +160 -0
  3. data/lib/client_side_validations/action_view/form_helper.rb +92 -0
  4. data/lib/client_side_validations/action_view/form_tag_helper.rb +12 -0
  5. data/lib/client_side_validations/action_view.rb +14 -0
  6. data/lib/client_side_validations/active_model/acceptance.rb +10 -0
  7. data/lib/client_side_validations/active_model/exclusion.rb +15 -0
  8. data/lib/client_side_validations/active_model/format.rb +10 -0
  9. data/lib/client_side_validations/active_model/inclusion.rb +15 -0
  10. data/lib/client_side_validations/active_model/length.rb +24 -0
  11. data/lib/client_side_validations/active_model/numericality.rb +31 -0
  12. data/lib/client_side_validations/active_model/presence.rb +10 -0
  13. data/lib/client_side_validations/active_model.rb +60 -0
  14. data/lib/client_side_validations/active_record/middleware.rb +33 -0
  15. data/lib/client_side_validations/active_record/uniqueness.rb +28 -0
  16. data/lib/client_side_validations/active_record.rb +11 -0
  17. data/lib/client_side_validations/core_ext/range.rb +10 -0
  18. data/lib/client_side_validations/core_ext/regexp.rb +14 -0
  19. data/lib/client_side_validations/core_ext.rb +3 -0
  20. data/lib/client_side_validations/engine.rb +6 -0
  21. data/lib/client_side_validations/files.rb +8 -0
  22. data/lib/client_side_validations/formtastic.rb +21 -0
  23. data/lib/client_side_validations/middleware.rb +81 -0
  24. data/lib/client_side_validations/mongo_mapper/middleware.rb +20 -0
  25. data/lib/client_side_validations/mongo_mapper/uniqueness.rb +28 -0
  26. data/lib/client_side_validations/mongo_mapper.rb +9 -0
  27. data/lib/client_side_validations/mongoid/middleware.rb +20 -0
  28. data/lib/client_side_validations/mongoid/uniqueness.rb +28 -0
  29. data/lib/client_side_validations/mongoid.rb +9 -0
  30. data/lib/client_side_validations/simple_form.rb +24 -0
  31. data/lib/client_side_validations/version.rb +3 -0
  32. data/lib/client_side_validations.rb +13 -0
  33. data/lib/generators/client_side_validations/copy_asset_generator.rb +36 -0
  34. data/lib/generators/client_side_validations/install_generator.rb +45 -0
  35. data/lib/generators/templates/client_side_validations/README.rails.3.0 +6 -0
  36. data/lib/generators/templates/client_side_validations/README.rails.3.1 +7 -0
  37. data/lib/generators/templates/client_side_validations/initializer.rb +14 -0
  38. data/test/action_view/cases/helper.rb +176 -0
  39. data/test/action_view/cases/test_helpers.rb +666 -0
  40. data/test/action_view/cases/test_legacy_helpers.rb +217 -0
  41. data/test/action_view/models/comment.rb +35 -0
  42. data/test/action_view/models/post.rb +35 -0
  43. data/test/action_view/models.rb +3 -0
  44. data/test/active_model/cases/helper.rb +4 -0
  45. data/test/active_model/cases/test_acceptance_validator.rb +16 -0
  46. data/test/active_model/cases/test_base.rb +11 -0
  47. data/test/active_model/cases/test_confirmation_validator.rb +16 -0
  48. data/test/active_model/cases/test_exclusion_validator.rb +20 -0
  49. data/test/active_model/cases/test_format_validator.rb +21 -0
  50. data/test/active_model/cases/test_inclusion_validator.rb +21 -0
  51. data/test/active_model/cases/test_length_validator.rb +61 -0
  52. data/test/active_model/cases/test_numericality_validator.rb +46 -0
  53. data/test/active_model/cases/test_presence_validator.rb +16 -0
  54. data/test/active_model/cases/test_validations.rb +175 -0
  55. data/test/active_model/models/person.rb +17 -0
  56. data/test/active_record/cases/helper.rb +12 -0
  57. data/test/active_record/cases/test_base.rb +11 -0
  58. data/test/active_record/cases/test_middleware.rb +175 -0
  59. data/test/active_record/cases/test_uniqueness_validator.rb +50 -0
  60. data/test/active_record/models/guid.rb +7 -0
  61. data/test/active_record/models/user.rb +14 -0
  62. data/test/base_helper.rb +7 -0
  63. data/test/core_ext/cases/test_core_ext.rb +46 -0
  64. data/test/formtastic/cases/helper.rb +7 -0
  65. data/test/formtastic/cases/test_form_builder.rb +11 -0
  66. data/test/formtastic/cases/test_form_helper.rb +21 -0
  67. data/test/generators/cases/test_generators.rb +70 -0
  68. data/test/javascript/config.ru +3 -0
  69. data/test/javascript/public/test/callbacks/elementAfter.js +54 -0
  70. data/test/javascript/public/test/callbacks/elementBefore.js +54 -0
  71. data/test/javascript/public/test/callbacks/elementFail.js +70 -0
  72. data/test/javascript/public/test/callbacks/elementPass.js +70 -0
  73. data/test/javascript/public/test/callbacks/formAfter.js +45 -0
  74. data/test/javascript/public/test/callbacks/formBefore.js +45 -0
  75. data/test/javascript/public/test/callbacks/formFail.js +51 -0
  76. data/test/javascript/public/test/callbacks/formPass.js +50 -0
  77. data/test/javascript/public/test/form_builders/validateForm.js +66 -0
  78. data/test/javascript/public/test/form_builders/validateFormtastic.js +54 -0
  79. data/test/javascript/public/test/form_builders/validateNestedForm.js +66 -0
  80. data/test/javascript/public/test/form_builders/validateSimpleForm.js +57 -0
  81. data/test/javascript/public/test/settings.js +15 -0
  82. data/test/javascript/public/test/validateElement.js +209 -0
  83. data/test/javascript/public/test/validators/acceptance.js +42 -0
  84. data/test/javascript/public/test/validators/confirmation.js +25 -0
  85. data/test/javascript/public/test/validators/exclusion.js +41 -0
  86. data/test/javascript/public/test/validators/format.js +27 -0
  87. data/test/javascript/public/test/validators/inclusion.js +42 -0
  88. data/test/javascript/public/test/validators/length.js +76 -0
  89. data/test/javascript/public/test/validators/numericality.js +158 -0
  90. data/test/javascript/public/test/validators/presence.js +21 -0
  91. data/test/javascript/public/test/validators/uniqueness.js +107 -0
  92. data/test/javascript/public/vendor/jquery.metadata.js +122 -0
  93. data/test/javascript/public/vendor/qunit.css +196 -0
  94. data/test/javascript/public/vendor/qunit.js +1374 -0
  95. data/test/javascript/server.rb +84 -0
  96. data/test/javascript/views/index.erb +20 -0
  97. data/test/javascript/views/layout.erb +21 -0
  98. data/test/middleware/cases/helper.rb +18 -0
  99. data/test/middleware/cases/test_middleware.rb +8 -0
  100. data/test/mongo_mapper/cases/helper.rb +9 -0
  101. data/test/mongo_mapper/cases/test_base.rb +15 -0
  102. data/test/mongo_mapper/cases/test_middleware.rb +77 -0
  103. data/test/mongo_mapper/cases/test_uniqueness_validator.rb +50 -0
  104. data/test/mongo_mapper/models/magazine.rb +11 -0
  105. data/test/mongoid/cases/helper.rb +16 -0
  106. data/test/mongoid/cases/test_base.rb +15 -0
  107. data/test/mongoid/cases/test_middleware.rb +77 -0
  108. data/test/mongoid/cases/test_uniqueness_validator.rb +49 -0
  109. data/test/mongoid/models/book.rb +12 -0
  110. data/test/simple_form/cases/helper.rb +5 -0
  111. data/test/simple_form/cases/test_form_builder.rb +14 -0
  112. data/test/simple_form/cases/test_form_helper.rb +24 -0
  113. data/test/test_loader.rb +6 -0
  114. data/vendor/assets/javascripts/rails.validations.js +418 -0
  115. metadata +436 -0
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+
3
+ require 'client_side_validations/core_ext'
4
+
5
+ module ClientSideValidations
6
+
7
+ module Middleware
8
+ class Validators
9
+ def initialize(app)
10
+ @app = app
11
+ end
12
+
13
+ def call(env)
14
+ case env['PATH_INFO']
15
+ when %r{\/validators\/(\w+)}
16
+ "::ClientSideValidations::Middleware::#{$1.camelize}".constantize.new(env).response
17
+ else
18
+ @app.call(env)
19
+ end
20
+ end
21
+ end
22
+
23
+ class Base
24
+ attr_accessor :request, :body, :status
25
+
26
+ def initialize(env)
27
+ self.body = ''
28
+ self.status = 200
29
+ self.request = ActionDispatch::Request.new(env)
30
+ end
31
+
32
+ def response
33
+ [status, {'Content-Type' => content_type, 'Content-Length' => body.length.to_s}, [body]]
34
+ end
35
+
36
+ def content_type
37
+ 'application/json'
38
+ end
39
+ end
40
+
41
+ class Uniqueness < Base
42
+ IGNORE_PARAMS = %w{case_sensitive id scope}
43
+
44
+ def response
45
+ if is_unique?
46
+ self.status = 404
47
+ self.body = 'true'
48
+ else
49
+ self.status = 200
50
+ self.body = 'false'
51
+ end
52
+ super
53
+ end
54
+
55
+ private
56
+
57
+ def is_unique?
58
+ resource = extract_resource
59
+ klass = resource.classify.constantize
60
+ attribute = request.params[resource].keys.first
61
+ value = request.params[resource][attribute]
62
+
63
+ if (defined?(::ActiveRecord::Base) && klass < ::ActiveRecord::Base)
64
+ middleware_klass = ClientSideValidations::ActiveRecord::Middleware
65
+ elsif (defined?(::Mongoid::Document) && klass.included_modules.include?(::Mongoid::Document))
66
+ middleware_klass = ClientSideValidations::Mongoid::Middleware
67
+ elsif (defined?(::MongoMapper::Document) && klass.included_modules.include?(::MongoMapper::Document))
68
+ middleware_klass = ClientSideValidations::MongoMapper::Middleware
69
+ end
70
+
71
+ middleware_klass.is_unique?(klass, attribute, value, request.params)
72
+ end
73
+
74
+ def extract_resource
75
+ parent_key = (request.params.keys - IGNORE_PARAMS).first
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
@@ -0,0 +1,20 @@
1
+ module ClientSideValidations::MongoMapper
2
+ class Middleware
3
+
4
+ # Still need to handle embedded documents
5
+ def self.is_unique?(klass, attribute, value, params)
6
+ if params[:case_sensitive] == 'false'
7
+ value = Regexp.new("^#{Regexp.escape(value.to_s)}$", Regexp::IGNORECASE)
8
+ end
9
+
10
+ criteria = klass.where(attribute => value)
11
+ criteria = criteria.where(:_id => {'$ne' => BSON::ObjectId(params[:id])}) if params[:id]
12
+
13
+ (params[:scope] || {}).each do |key, value|
14
+ criteria = criteria.where(key => value)
15
+ end
16
+
17
+ !criteria.exists?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ module ClientSideValidations::MongoMapper
2
+ module Uniqueness
3
+ def client_side_hash(model, attribute)
4
+ hash = {}
5
+ hash[:message] = model.errors.generate_message(attribute, message_type, options.except(:scope))
6
+ hash[:case_sensitive] = options[:case_sensitive] if options.key?(:case_sensitive)
7
+ hash[:id] = model.id unless model.new_record?
8
+ if options.key?(:scope) && options[:scope].present?
9
+ hash[:scope] = Array.wrap(options[:scope]).inject({}) do |scope_hash, scope_item|
10
+ scope_hash.merge!(scope_item => model.send(scope_item))
11
+ end
12
+ end
13
+
14
+ unless model.class.name.demodulize == model.class.name
15
+ hash[:class] = model.class.name.underscore
16
+ end
17
+
18
+ hash
19
+ end
20
+
21
+ private
22
+
23
+ def message_type
24
+ :taken
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,9 @@
1
+ require 'client_side_validations/active_model'
2
+ require 'client_side_validations/mongo_mapper/middleware'
3
+
4
+ %w{uniqueness}.each do |validator|
5
+ require "client_side_validations/mongo_mapper/#{validator}"
6
+ validator.capitalize!
7
+ eval "MongoMapper::Plugins::Validations::#{validator}Validator.send(:include, ClientSideValidations::MongoMapper::#{validator})"
8
+ end
9
+
@@ -0,0 +1,20 @@
1
+ module ClientSideValidations::Mongoid
2
+ class Middleware
3
+
4
+ # Still need to handle embedded documents
5
+ def self.is_unique?(klass, attribute, value, params)
6
+ if params[:case_sensitive] == 'false'
7
+ value = Regexp.new("^#{Regexp.escape(value.to_s)}$", Regexp::IGNORECASE)
8
+ end
9
+
10
+ criteria = klass.where(attribute => value)
11
+ criteria = criteria.where(:_id => {'$ne' => BSON::ObjectId(params[:id])}) if params[:id]
12
+
13
+ (params[:scope] || {}).each do |key, value|
14
+ criteria = criteria.where(key => value)
15
+ end
16
+
17
+ !criteria.exists?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ module ClientSideValidations::Mongoid
2
+ module Uniqueness
3
+ def client_side_hash(model, attribute)
4
+ hash = {}
5
+ hash[:message] = model.errors.generate_message(attribute, message_type, options.except(:scope))
6
+ hash[:case_sensitive] = options[:case_sensitive] if options.key?(:case_sensitive)
7
+ hash[:id] = model.id unless model.new_record?
8
+ if options.key?(:scope) && options[:scope].present?
9
+ hash[:scope] = Array.wrap(options[:scope]).inject({}) do |scope_hash, scope_item|
10
+ scope_hash.merge!(scope_item => model.send(scope_item))
11
+ end
12
+ end
13
+
14
+ unless model.class.name.demodulize == model.class.name
15
+ hash[:class] = model.class.name.underscore
16
+ end
17
+
18
+ hash
19
+ end
20
+
21
+ private
22
+
23
+ def message_type
24
+ :taken
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,9 @@
1
+ require 'client_side_validations/active_model'
2
+ require 'client_side_validations/mongoid/middleware'
3
+
4
+ %w{uniqueness}.each do |validator|
5
+ require "client_side_validations/mongoid/#{validator}"
6
+ validator.capitalize!
7
+ eval "Mongoid::Validations::#{validator}Validator.send(:include, ClientSideValidations::Mongoid::#{validator})"
8
+ end
9
+
@@ -0,0 +1,24 @@
1
+ module ClientSideValidations
2
+ module SimpleForm
3
+ module FormBuilder
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ def self.client_side_form_settings(options, form_helper)
8
+ {
9
+ :type => self.to_s,
10
+ :error_class => ::SimpleForm.error_class,
11
+ :error_tag => ::SimpleForm.error_tag,
12
+ :wrapper_error_class => ::SimpleForm.wrapper_error_class,
13
+ :wrapper_tag => ::SimpleForm.wrapper_tag
14
+ }
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+
23
+ SimpleForm::FormBuilder.send(:include, ClientSideValidations::SimpleForm::FormBuilder)
24
+
@@ -0,0 +1,3 @@
1
+ module ClientSideValidations
2
+ VERSION = '3.1.4.af1'
3
+ end
@@ -0,0 +1,13 @@
1
+ module ClientSideValidations
2
+ end
3
+
4
+ require 'client_side_validations/active_model' if defined?(::ActiveModel)
5
+ require 'client_side_validations/active_record' if defined?(::ActiveRecord)
6
+ require 'client_side_validations/mongoid' if defined?(::Mongoid)
7
+ require 'client_side_validations/mongo_mapper' if defined?(::MongoMapper)
8
+ require 'client_side_validations/action_view' if defined?(::ActionView)
9
+ if defined?(::Rails)
10
+ require 'client_side_validations/middleware'
11
+ require 'client_side_validations/engine'
12
+ end
13
+
@@ -0,0 +1,36 @@
1
+ module ClientSideValidations
2
+ module Generators
3
+ class CopyAssetGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../../../../vendor/assets/javascripts', __FILE__)
5
+
6
+ private
7
+
8
+ def self.asset_pipeline_enabled?
9
+ (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
10
+ end
11
+
12
+ def asset_pipeline_enabled?
13
+ self.class.asset_pipeline_enabled?
14
+ end
15
+
16
+ public
17
+
18
+ if asset_pipeline_enabled?
19
+ desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to app/assets/javascripts.'
20
+ else
21
+ desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
22
+ end
23
+
24
+ def copy_javascript_asset
25
+ if asset_pipeline_enabled?
26
+ destination = 'app/assets/javascripts'
27
+ else
28
+ destination = 'public/javascripts'
29
+ end
30
+
31
+ copy_file 'rails.validations.js', "#{destination}/rails.validations.js"
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,45 @@
1
+ module ClientSideValidations
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../../templates/client_side_validations', __FILE__)
5
+
6
+ private
7
+
8
+ def self.asset_pipeline_enabled?
9
+ (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
10
+ end
11
+
12
+ def asset_pipeline_enabled?
13
+ self.class.asset_pipeline_enabled?
14
+ end
15
+
16
+ public
17
+
18
+ if asset_pipeline_enabled?
19
+ desc 'Creates a ClientSideValidations initializer.'
20
+ else
21
+ desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
22
+ end
23
+
24
+ def copy_initializer
25
+ copy_file 'initializer.rb', 'config/initializers/client_side_validations.rb'
26
+ end
27
+
28
+ def copy_javascript_asset
29
+ unless asset_pipeline_enabled?
30
+ copy_file '../../../../vendor/assets/javascripts/rails.validations.js', 'public/javascripts/rails.validations.js'
31
+ end
32
+ end
33
+
34
+ def show_readme
35
+ if Rails.version >= '3.1'
36
+ readme 'README.rails.3.1' if behavior == :invoke
37
+ else
38
+ readme 'README.rails.3.0' if behavior == :invoke
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,6 @@
1
+ *********************
2
+ ClientSideValidations
3
+ *********************
4
+
5
+ Client Side Validations only works with jQuery.
6
+ You'll need to include jQuery in your layout file before you include 'rails.validations.js'
@@ -0,0 +1,7 @@
1
+ *********************
2
+ ClientSideValidations
3
+ *********************
4
+
5
+ In your app/assets/javascripts/application.js file add the following:
6
+
7
+ //= require rails.validations
@@ -0,0 +1,14 @@
1
+ # ClientSideValidations Initializer
2
+
3
+ require 'client_side_validations/simple_form' if defined?(::SimpleForm)
4
+ require 'client_side_validations/formtastic' if defined?(::Formtastic)
5
+
6
+ # Uncomment the following block if you want each input field to have the validation messages attached.
7
+ # ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
8
+ # unless html_tag =~ /^<label/
9
+ # %{<div class="field_with_errors">#{html_tag}<label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label></div>}.html_safe
10
+ # else
11
+ # %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
12
+ # end
13
+ # end
14
+
@@ -0,0 +1,176 @@
1
+ require 'base_helper'
2
+ require 'action_view'
3
+ require 'action_view/template'
4
+ require 'action_view/models'
5
+ require 'client_side_validations/action_view'
6
+
7
+ module ActionController
8
+ class Base
9
+ include ActionDispatch::Routing::RouteSet.new.url_helpers
10
+ end
11
+ end
12
+
13
+ module ActionViewTestSetup
14
+ include ::ClientSideValidations::ActionView::Helpers::FormHelper
15
+ include ::ClientSideValidations::ActionView::Helpers::FormTagHelper
16
+
17
+ def form_for(*)
18
+ @output_buffer = super
19
+ end
20
+
21
+ Routes = ActionDispatch::Routing::RouteSet.new
22
+ Routes.draw do
23
+ resources :posts do
24
+ resources :comments
25
+ end
26
+ end
27
+
28
+ def _routes
29
+ Routes
30
+ end
31
+
32
+ include Routes.url_helpers
33
+
34
+ def setup
35
+ super
36
+
37
+ # Create "label" locale for testing I18n label helpers
38
+ I18n.backend.store_translations 'label', {
39
+ :activemodel => {
40
+ :attributes => {
41
+ :post => {
42
+ :cost => "Total cost"
43
+ }
44
+ }
45
+ },
46
+ :helpers => {
47
+ :label => {
48
+ :post => {
49
+ :body => "Write entire text here"
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ # Create "submit" locale for testing I18n submit helpers
56
+ I18n.backend.store_translations 'submit', {
57
+ :helpers => {
58
+ :submit => {
59
+ :create => 'Create %{model}',
60
+ :update => 'Confirm %{model} changes',
61
+ :submit => 'Save changes',
62
+ :another_post => {
63
+ :update => 'Update your %{model}'
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ @post = Post.new
70
+ @comment = Comment.new
71
+ def @post.errors()
72
+ Class.new{
73
+ def [](field); field == "author_name" ? ["can't be empty"] : [] end
74
+ def empty?() false end
75
+ def count() 1 end
76
+ def full_messages() [ "Author name can't be empty" ] end
77
+ }.new
78
+ end
79
+ def @post.id; 123; end
80
+ def @post.id_before_type_cast; 123; end
81
+ def @post.to_param; '123'; end
82
+
83
+ @post.persisted = true
84
+ @post.title = "Hello World"
85
+ @post.author_name = ""
86
+ @post.body = "Back to the hill and over it again!"
87
+ @post.secret = 1
88
+ @post.written_on = Date.new(2004, 6, 15)
89
+
90
+ if defined?(ActionView::OutputFlow)
91
+ @view_flow = ActionView::OutputFlow.new
92
+ else
93
+ @_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
94
+ end
95
+ end
96
+
97
+ def snowman(method = nil)
98
+ txt = %{<div style="margin:0;padding:0;display:inline">}
99
+ txt << %{<input name="utf8" type="hidden" value="&#x2713;" />}
100
+ txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
101
+ txt << %{</div>}
102
+ end
103
+
104
+ def form_text(action = "http://www.example.com", id = nil, html_class = nil, remote = nil, validators = nil, file = nil)
105
+ txt = %{<form accept-charset="UTF-8" action="#{action}"}
106
+ txt << %{ data-remote="true"} if remote
107
+ txt << %{ class="#{html_class}"} if html_class
108
+ txt << %{ data-validate="true"} if validators
109
+ txt << %{ enctype="multipart/form-data"} if file
110
+ txt << %{ id="#{id}"} if id
111
+ txt << %{ method="post"}
112
+ txt << %{ novalidate="novalidate"} if validators
113
+ txt << %{>}
114
+ end
115
+
116
+ def whole_form(action = "http://www.example.com", id = nil, html_class = nil, options = nil)
117
+ contents = block_given? ? yield : ""
118
+
119
+ if options.is_a?(Hash)
120
+ method, remote, validators, file = options.values_at(:method, :remote, :validators, :file)
121
+ else
122
+ method = options
123
+ end
124
+
125
+ html = form_text(action, id, html_class, remote, validators, file) + snowman(method) + (contents || "") + "</form>"
126
+
127
+ if options.is_a?(Hash) && options[:validators]
128
+ build_script_tag(html, id, options[:validators])
129
+ else
130
+ html
131
+ end
132
+ end
133
+
134
+ def build_script_tag(html, id, validators)
135
+ (html || "") + %Q{<script>window['#{id}'] = #{client_side_form_settings_helper.merge(:validators => validators).to_json};</script>}
136
+ end
137
+
138
+ protected
139
+ def comments_path(post)
140
+ "/posts/#{post.id}/comments"
141
+ end
142
+ alias_method :post_comments_path, :comments_path
143
+
144
+ def comment_path(post, comment)
145
+ "/posts/#{post.id}/comments/#{comment.id}"
146
+ end
147
+ alias_method :post_comment_path, :comment_path
148
+
149
+ def admin_comments_path(post)
150
+ "/admin/posts/#{post.id}/comments"
151
+ end
152
+ alias_method :admin_post_comments_path, :admin_comments_path
153
+
154
+ def admin_comment_path(post, comment)
155
+ "/admin/posts/#{post.id}/comments/#{comment.id}"
156
+ end
157
+ alias_method :admin_post_comment_path, :admin_comment_path
158
+
159
+ def posts_path
160
+ "/posts"
161
+ end
162
+
163
+ def post_path(post, options = {})
164
+ if options[:format]
165
+ "/posts/#{post.id}.#{options[:format]}"
166
+ else
167
+ "/posts/#{post.id}"
168
+ end
169
+ end
170
+
171
+ def protect_against_forgery?
172
+ false
173
+ end
174
+
175
+ end
176
+