ajax_validator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +87 -0
- data/Rakefile +36 -0
- data/app/assets/javascripts/ajax_validator/ajax_validator.js.coffee +46 -0
- data/app/assets/javascripts/ajax_validator/application.js +13 -0
- data/app/assets/stylesheets/ajax_validator/application.css +15 -0
- data/app/controllers/ajax_validator/application_controller.rb +4 -0
- data/app/controllers/ajax_validator/validators_controller.rb +68 -0
- data/app/helpers/ajax_validator/application_helper.rb +4 -0
- data/app/models/ajax_validator/concerns/validation.rb +21 -0
- data/app/models/ajax_validator/validator.rb +128 -0
- data/app/views/layouts/ajax_validator/application.html.erb +14 -0
- data/config/cucumber.yml +8 -0
- data/config/routes.rb +3 -0
- data/lib/ajax_validator/engine.rb +42 -0
- data/lib/ajax_validator/version.rb +3 -0
- data/lib/ajax_validator.rb +4 -0
- data/lib/tasks/ajax_validator_tasks.rake +4 -0
- data/lib/tasks/cucumber.rake +65 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/base_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +32 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +110 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +715 -0
- data/spec/dummy/log/test.log +294 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/rails_helper.rb +68 -0
- data/spec/route_helper.rb +6 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/support/capybara.rb +35 -0
- data/spec/support/database_cleaner.rb +77 -0
- data/spec/support/factory_girl_rails.rb +32 -0
- data/spec/support/matchers.rb +21 -0
- metadata +408 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7ea11a9a26ae42ec77a8b1513400c90c09299e53
|
4
|
+
data.tar.gz: 39a0f8bb6725c27919e8eba0534585c816bddc1e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6bf4253121c5c57cd0590f7f7a9c3d6c767195a1831523d9e7615224d456e186c768ff9063e1396e3d93f0069be3b4cb4c156d8b238ab7eb58dec90f43661349
|
7
|
+
data.tar.gz: dc01803395572d253fd2e0d86b52fd38f59d5530759c84222271e78d520bccf40b102d1f976f2a968774f45d89cc0b6235828be57788a7214c691109d5b415e1
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 efigence
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Ajax Validator [](http://travis-ci.org/efigence/ajax_validator)
|
2
|
+
|
3
|
+
### Ajax Live Form Validation Rails Engine
|
4
|
+
|
5
|
+
## How to install
|
6
|
+
|
7
|
+
1. Add to `Gemfile`
|
8
|
+
|
9
|
+
gem 'ajax_validator', path: 'vendor/engines/ajax_validator'
|
10
|
+
2. Bundle
|
11
|
+
|
12
|
+
bundle install
|
13
|
+
3. Create file `config/initializers/ajax_validator.rb` and specify validatable models
|
14
|
+
|
15
|
+
AjaxValidator::Engine.setup do |config|
|
16
|
+
config.ajax_validator_engine = {
|
17
|
+
# if form object is used, both classes must be put here
|
18
|
+
whitelist_models: ['some_klass', 'some_module/some_klass']
|
19
|
+
}
|
20
|
+
end
|
21
|
+
4. Copy migration (currently, not needed)
|
22
|
+
|
23
|
+
bundle exec rake ajax_validator:install:migrations
|
24
|
+
5. Run migration (currently, not needed)
|
25
|
+
|
26
|
+
bundle exec rake db:migrate SCOPE=ajax_validator
|
27
|
+
6. Run seeds (currently, not needed)
|
28
|
+
|
29
|
+
bundle exec rake ajax_validator:db:seed
|
30
|
+
7. Add to `config/routes.rb`
|
31
|
+
|
32
|
+
mount AjaxValidator::Engine, at: '/ajax_validator'
|
33
|
+
|
34
|
+
## How to use helpers
|
35
|
+
|
36
|
+
Include the needed javascript file in your application.js or application.js.coffee
|
37
|
+
|
38
|
+
Javascript
|
39
|
+
//= require ajax_validator/application
|
40
|
+
|
41
|
+
or CoffeeScript
|
42
|
+
#= require ajax_validator/application
|
43
|
+
|
44
|
+
Script will add class 'has-error' or 'has-success' to the field wrapping div, based on the result.
|
45
|
+
|
46
|
+
Add these attributes on text input field:
|
47
|
+
class: 'ajax_validator__field'
|
48
|
+
data-form-object='validations/signup_form_company_name' [Optional, leave empty string '' validate on model directly]
|
49
|
+
data-resource-model='company'
|
50
|
+
data-resource-attr-name='name'
|
51
|
+
data-ignore-resource-attr-value='false' [Optional, set to 'true' when attribute is assembled from additional params instead]
|
52
|
+
data-resource-instance-additional-params='{"something": true, "something_else": ""}' [Optional]
|
53
|
+
|
54
|
+
Example on Bootstrap:
|
55
|
+
|
56
|
+
ERB:
|
57
|
+
<div class="input-group">
|
58
|
+
<input class='form-control ajax_validator__field' data-form-object='validations/signup_form_company_name' data-resource-model='company' data-resource-attr-name='name' type='text' name='signup_form[company]' id='signup_form_company'>
|
59
|
+
</div>
|
60
|
+
|
61
|
+
or HAML:
|
62
|
+
.input-group
|
63
|
+
= f.text_field :company, class: 'form-control ajax_validator__field', data: {form_object: 'validations/signup_form_company_name', resource_model: 'company', resource_attr_name: 'name'}
|
64
|
+
|
65
|
+
### How to add a new gem to the engine
|
66
|
+
- Add a gem to `Gemfile`
|
67
|
+
- Run: `bundle`
|
68
|
+
- Copy over to multiple gemfiles: `bundle exec appraisal install`
|
69
|
+
|
70
|
+
### How to test
|
71
|
+
cd vendor/engines/ajax_validator/
|
72
|
+
export DATABASE_URL='postgres://localhost:5432' AJAX_VALIDATOR_DATABASE_USERNAME=postgres AJAX_VALIDATOR_DATABASE_PASSWORD=p
|
73
|
+
|
74
|
+
bundle exec appraisal rails-4.1 rake db:create db:migrate db:seed
|
75
|
+
---
|
76
|
+
- Optional:
|
77
|
+
|
78
|
+
bundle exec appraisal rails-4.1 rake db:schema:load RAILS_ENV=test
|
79
|
+
---
|
80
|
+
|
81
|
+
bundle exec appraisal rails-4.1 rake spec
|
82
|
+
bundle exec appraisal rails-4.1 rake app:cucumber
|
83
|
+
|
84
|
+
## How to develop
|
85
|
+
bundle exec rails g scaffold Post name:string --integration_tool=rspec --helper=false --assets=false
|
86
|
+
bundle exec rails g cucumber_scaffold:feature Post name:string
|
87
|
+
bundle exec rails db:migrate
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
8
|
+
load 'rails/tasks/engine.rake'
|
9
|
+
|
10
|
+
#load 'rails/tasks/statistics.rake'
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
|
15
|
+
require 'rspec/core'
|
16
|
+
require 'rspec/core/rake_task'
|
17
|
+
require 'appraisal'
|
18
|
+
|
19
|
+
task :default => :spec
|
20
|
+
|
21
|
+
# RSpec::Core::RakeTask.new(:spec)
|
22
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
23
|
+
|
24
|
+
desc 'Default'
|
25
|
+
task :default do
|
26
|
+
if ENV['BUNDLE_GEMFILE'] =~ /gemfiles/
|
27
|
+
#Rake::Task['app:db:test:prepare'].invoke
|
28
|
+
Rake::Task['spec'].invoke
|
29
|
+
else
|
30
|
+
Rake::Task['appraise'].invoke
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
task :appraise do
|
35
|
+
exec 'appraisal install && appraisal rake'
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
window.ajax_validator_timeout = undefined
|
2
|
+
|
3
|
+
$(document).on 'ready', (_event) ->
|
4
|
+
$('form').on 'keydown', '.ajax_validator__field', (e) ->
|
5
|
+
|
6
|
+
form_object = $(@).data('form-object')
|
7
|
+
resource_model = $(@).data('resource-model')
|
8
|
+
resource_attr_name = $(@).data('resource-attr-name')
|
9
|
+
ignore_resource_attr_value = $(@).data('ignore-resource-attr-value')
|
10
|
+
resource_instance_additional_params = $(@).data('resource-instance-additional-params')
|
11
|
+
|
12
|
+
queue_id = form_object + '-' + resource_model + resource_attr_name
|
13
|
+
|
14
|
+
$(document).queue queue_id, (next) =>
|
15
|
+
|
16
|
+
parent_div = $(@).parents('div').eq(0)
|
17
|
+
resource_attr_value = $(@).val()
|
18
|
+
|
19
|
+
$.ajax
|
20
|
+
url: "/ajax_validator/validators"
|
21
|
+
type: "POST"
|
22
|
+
dataType: "json"
|
23
|
+
data:
|
24
|
+
'validator':
|
25
|
+
'form_object': form_object
|
26
|
+
'resource_model': resource_model
|
27
|
+
'resource_attr_name': resource_attr_name
|
28
|
+
'resource_attr_value': resource_attr_value
|
29
|
+
'ignore_resource_attr_value': ignore_resource_attr_value
|
30
|
+
'resource_instance_additional_params': resource_instance_additional_params
|
31
|
+
success: (returnData) ->
|
32
|
+
if parent_div
|
33
|
+
if returnData['errors'].length > 0
|
34
|
+
$(parent_div).removeClass("has-error has-success").addClass("has-error")
|
35
|
+
else
|
36
|
+
$(parent_div).removeClass("has-error has-success").addClass("has-success")
|
37
|
+
else
|
38
|
+
$('body').html(JSON.stringify returnData)
|
39
|
+
error: (e) ->
|
40
|
+
# console.log(JSON.stringify e)
|
41
|
+
|
42
|
+
clearTimeout(ajax_validator_timeout);
|
43
|
+
|
44
|
+
window.ajax_validator_timeout = setTimeout((->
|
45
|
+
$(document).dequeue queue_id
|
46
|
+
), 1000)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_dependency 'ajax_validator/application_controller'
|
2
|
+
|
3
|
+
module AjaxValidator
|
4
|
+
class ValidatorsController < ApplicationController
|
5
|
+
skip_before_action :verify_authenticity_token, only: [:create]
|
6
|
+
|
7
|
+
# POST /validators
|
8
|
+
#
|
9
|
+
# {
|
10
|
+
# 'validator': {
|
11
|
+
# 'form_object': 'validations/signup_form_company_name',
|
12
|
+
# 'resource_model': 'company'
|
13
|
+
# 'resource_attr_name': 'name',
|
14
|
+
# 'resource_attr_value': 'Efigence'
|
15
|
+
# }
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# or:
|
19
|
+
#
|
20
|
+
# {
|
21
|
+
# 'validator': {
|
22
|
+
# 'form_object': '',
|
23
|
+
# 'resource_model': 'company'
|
24
|
+
# 'resource_attr_name': 'name',
|
25
|
+
# 'resource_attr_value': 'Efigence'
|
26
|
+
# }
|
27
|
+
# }
|
28
|
+
#
|
29
|
+
# Response (jsonapi.org format)
|
30
|
+
#
|
31
|
+
# on success:
|
32
|
+
#
|
33
|
+
# {
|
34
|
+
# 'errors': []
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# on failure:
|
38
|
+
#
|
39
|
+
# {
|
40
|
+
# 'errors': [
|
41
|
+
# {
|
42
|
+
# 'name': [
|
43
|
+
# 'has already been taken'
|
44
|
+
# ]
|
45
|
+
# }
|
46
|
+
# ]
|
47
|
+
# }
|
48
|
+
def create
|
49
|
+
validated = Validator.new(validator_params).validate
|
50
|
+
response = { 'errors' => validated.errors.messages.stringify_keys.map{|i| {i[0] => i[1]}} }
|
51
|
+
render json: response.to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Only allow a trusted parameter 'white list' through.
|
57
|
+
def validator_params
|
58
|
+
wildcard = params.try(:[], :validator).try(:[], :resource_instance_additional_params).try(:keys)
|
59
|
+
params.require(:validator).
|
60
|
+
permit(:form_object,
|
61
|
+
:resource_model,
|
62
|
+
:resource_attr_name,
|
63
|
+
:resource_attr_value,
|
64
|
+
:ignore_resource_attr_value,
|
65
|
+
:resource_instance_additional_params => wildcard)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AjaxValidator
|
2
|
+
module Concerns
|
3
|
+
module Validation
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
private
|
7
|
+
def ajax_validator_valid_attribute?(resource_attr_name, resource_attr_value, model_instance = self)
|
8
|
+
model_instance.class.validators_on(resource_attr_name.to_sym).each do |validator|
|
9
|
+
if validator.options[:if]
|
10
|
+
next unless !!model_instance.send(validator.options[:if])
|
11
|
+
end
|
12
|
+
if validator.options[:unless]
|
13
|
+
next if !!model_instance.send(validator.options[:unless])
|
14
|
+
end
|
15
|
+
validator.validate_each(model_instance, resource_attr_name.to_sym, resource_attr_value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# Use with form object that responds to `validate` method,
|
2
|
+
# e.g. use Reform or Virtus with ActiveModel::Validations
|
3
|
+
#
|
4
|
+
# Open the console and try:
|
5
|
+
#
|
6
|
+
# validator_params = { form_object: 'validations/signup_form_company_name',
|
7
|
+
# resource_model: 'company',
|
8
|
+
# resource_attr_name: 'name',
|
9
|
+
# resource_attr_value: 'Efigence' }
|
10
|
+
#
|
11
|
+
# One can use the engine with any ActiveModel::Model object with ActiveModel::Validations
|
12
|
+
# included. For performance, even if the model is clobbered with validations, only validations
|
13
|
+
# on the specified field one will be fired. Examples:
|
14
|
+
#
|
15
|
+
# validator_params = { form_object: '',
|
16
|
+
# resource_model: 'company',
|
17
|
+
# resource_attr_name: 'name',
|
18
|
+
# resource_attr_value: 'efigence' }
|
19
|
+
#
|
20
|
+
# Validate (also conditionally) virtual or model attribute set inside some before validation callback:
|
21
|
+
#
|
22
|
+
# validator_params = { form_object: '',
|
23
|
+
# resource_model: 'company',
|
24
|
+
# resource_attr_name: 'vat_number_with_prefix',
|
25
|
+
# resource_attr_value: '',
|
26
|
+
# ignore_resource_attr_value: 'true',
|
27
|
+
# resource_instance_additional_params: {country: 'Poland',
|
28
|
+
# vat_number: '0123456789'} }
|
29
|
+
#
|
30
|
+
# validator_params = { form_object: '',
|
31
|
+
# resource_model: 'company',
|
32
|
+
# resource_attr_name: 'vat_number',
|
33
|
+
# resource_attr_value: '',
|
34
|
+
# ignore_resource_attr_value: 'true',
|
35
|
+
# resource_instance_additional_params: {business_owner: true,
|
36
|
+
# vat_number: ''} }
|
37
|
+
#
|
38
|
+
# validator = AjaxValidator::Validator.new(validator_params)
|
39
|
+
# tested_company = validator.validate
|
40
|
+
# tested_company.errors.to_a
|
41
|
+
#
|
42
|
+
# - `resource_instance_additional_params` hash is passed as args to given active model instance,
|
43
|
+
# to handle before validation callbacks' dependencies, however, if form object is used,
|
44
|
+
# additional params - if specified - must be handled by form object instance itself,
|
45
|
+
# implementations may vary.
|
46
|
+
# - set `ignore_resource_attr_value` to 'true' if attribute value is assembled inside before validation
|
47
|
+
# callback
|
48
|
+
# - validating virtual attributes, custom validation methods and custom validators are all supported
|
49
|
+
module AjaxValidator
|
50
|
+
class Validator
|
51
|
+
|
52
|
+
def initialize(params = {})
|
53
|
+
@form_object = params[:form_object] # optional
|
54
|
+
@resource_model = params[:resource_model]
|
55
|
+
@resource_attr_name = params[:resource_attr_name]
|
56
|
+
@resource_attr_value = params[:resource_attr_value]
|
57
|
+
# skip setter if attribute is being assembled inside before validation callback
|
58
|
+
@ignore_resource_attr_value = params[:ignore_resource_attr_value].to_s == 'true'
|
59
|
+
if params[:resource_instance_additional_params].present?
|
60
|
+
@resource_instance_additional_params = params[:resource_instance_additional_params]
|
61
|
+
end
|
62
|
+
@bypass_whitelist = false
|
63
|
+
end
|
64
|
+
|
65
|
+
attr_accessor :form_object, :resource_model, :resource_attr_name, :resource_attr_value, :resource_instance_additional_params, :ignore_resource_attr_value, :bypass_whitelist
|
66
|
+
|
67
|
+
def validate
|
68
|
+
form_object_klass, resource_model_klass = safely_constantized_klasses
|
69
|
+
if form_object_klass
|
70
|
+
validate_form_object(resource_model_klass, form_object_klass)
|
71
|
+
else
|
72
|
+
validate_resource_model(resource_model_klass)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def safely_constantized_klasses
|
79
|
+
if form_object.present?
|
80
|
+
guard_whitelist(form_object)
|
81
|
+
form_object_klass = constantize_klass(form_object)
|
82
|
+
else
|
83
|
+
form_object_klass = nil
|
84
|
+
end
|
85
|
+
guard_whitelist(resource_model)
|
86
|
+
resource_model_klass = constantize_klass(resource_model)
|
87
|
+
[form_object_klass, resource_model_klass]
|
88
|
+
end
|
89
|
+
|
90
|
+
def constantize_klass(klass)
|
91
|
+
klass.to_s.classify.constantize
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_form_object(resource_model_klass, form_object_klass)
|
95
|
+
if resource_instance_additional_params
|
96
|
+
resource_instance = resource_model_klass.new(resource_instance_additional_params)
|
97
|
+
else
|
98
|
+
resource_instance = resource_model_klass.new
|
99
|
+
end
|
100
|
+
# support composition
|
101
|
+
klass_object = form_object_klass.new(resource_model.to_s => resource_instance) rescue nil
|
102
|
+
klass_object ||= form_object_klass.new(resource_instance)
|
103
|
+
klass_object.validate(resource_attr_name.to_s => resource_attr_value.to_s)
|
104
|
+
klass_object
|
105
|
+
end
|
106
|
+
|
107
|
+
def validate_resource_model(resource_model_klass)
|
108
|
+
klass_object = resource_model_klass.new(resource_instance_additional_params)
|
109
|
+
# run before_validation callback for active model (https://github.com/rails/rails/issues/718#issuecomment-1170499)
|
110
|
+
klass_object.try(:run_callbacks, :validation) { false }
|
111
|
+
if ignore_resource_attr_value
|
112
|
+
klass_object.send(:ajax_validator_valid_attribute?, resource_attr_name.to_s, klass_object.try(:send, resource_attr_name))
|
113
|
+
else
|
114
|
+
klass_object.send(:ajax_validator_valid_attribute?, resource_attr_name.to_s, resource_attr_value.to_s)
|
115
|
+
end
|
116
|
+
klass_object
|
117
|
+
end
|
118
|
+
|
119
|
+
def guard_whitelist(object)
|
120
|
+
unless bypass_whitelist
|
121
|
+
unless AjaxValidator::Engine.config[:whitelist_klasses].to_a.map{|i| i.to_s.underscore}.include?(object.to_s.underscore)
|
122
|
+
raise 'Class was not whitelisted!'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>AjaxValidator</title>
|
5
|
+
<%= stylesheet_link_tag "ajax_validator/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "ajax_validator/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/config/cucumber.yml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
<%
|
2
|
+
rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
|
3
|
+
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
|
4
|
+
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
|
5
|
+
%>
|
6
|
+
default: <%= std_opts %> features
|
7
|
+
wip: --tags @wip:3 --wip features
|
8
|
+
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
|
data/config/routes.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module AjaxValidator
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace AjaxValidator
|
4
|
+
|
5
|
+
config.generators do |g|
|
6
|
+
g.test_framework :rspec, :fixture => false
|
7
|
+
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
8
|
+
end
|
9
|
+
|
10
|
+
config.to_prepare do
|
11
|
+
Rails.application.config.try(:ajax_validator_engine).try(:[], :whitelist_klasses).to_a.each do |whitelist_klass|
|
12
|
+
begin
|
13
|
+
klass = whitelist_klass.to_s.classify.constantize
|
14
|
+
rescue
|
15
|
+
raise "Can\'t constantize from \'#{whitelist_klass}\'. Check if class exists."
|
16
|
+
end
|
17
|
+
klass.include AjaxValidator::Concerns::Validation
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.setup(&block)
|
22
|
+
@@config ||= AjaxValidator::Engine::Configuration.new
|
23
|
+
yield @@config if block
|
24
|
+
return @@config
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.config
|
28
|
+
puts 'WARNING: ajax_validator_engine not configured' unless Rails.application.config.try(:ajax_validator_engine)
|
29
|
+
Rails.application.config.ajax_validator_engine
|
30
|
+
end
|
31
|
+
|
32
|
+
# will not reload in development
|
33
|
+
#initializer :prepare_models_for_ajax_validator do |app|
|
34
|
+
#end
|
35
|
+
|
36
|
+
#config.to_prepare do
|
37
|
+
# Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
|
38
|
+
# require_dependency(c)
|
39
|
+
# end
|
40
|
+
#end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
|
2
|
+
# It is recommended to regenerate this file in the future when you upgrade to a
|
3
|
+
# newer version of cucumber-rails. Consider adding your own code to a new file
|
4
|
+
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
5
|
+
# files.
|
6
|
+
|
7
|
+
|
8
|
+
unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
|
9
|
+
|
10
|
+
vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
11
|
+
$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'cucumber/rake/task'
|
15
|
+
|
16
|
+
namespace :cucumber do
|
17
|
+
Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
|
18
|
+
t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
|
19
|
+
t.fork = true # You may get faster startup if you set this to false
|
20
|
+
t.profile = 'default'
|
21
|
+
end
|
22
|
+
|
23
|
+
Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
|
24
|
+
t.binary = vendored_cucumber_bin
|
25
|
+
t.fork = true # You may get faster startup if you set this to false
|
26
|
+
t.profile = 'wip'
|
27
|
+
end
|
28
|
+
|
29
|
+
Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
|
30
|
+
t.binary = vendored_cucumber_bin
|
31
|
+
t.fork = true # You may get faster startup if you set this to false
|
32
|
+
t.profile = 'rerun'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Run all features'
|
36
|
+
task :all => [:ok, :wip]
|
37
|
+
|
38
|
+
task :statsetup do
|
39
|
+
require 'rails/code_statistics'
|
40
|
+
::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
|
41
|
+
::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
desc 'Alias for cucumber:ok'
|
45
|
+
task :cucumber => 'cucumber:ok'
|
46
|
+
|
47
|
+
task :default => :cucumber
|
48
|
+
|
49
|
+
task :features => :cucumber do
|
50
|
+
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
51
|
+
end
|
52
|
+
|
53
|
+
# In case we don't have ActiveRecord, append a no-op task that we can depend upon.
|
54
|
+
task 'db:test:prepare' do
|
55
|
+
end
|
56
|
+
|
57
|
+
task :stats => 'cucumber:statsetup'
|
58
|
+
rescue LoadError
|
59
|
+
desc 'cucumber rake task not available (cucumber not installed)'
|
60
|
+
task :cucumber do
|
61
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|