padrino-validation-html5 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.
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/Gemfile +16 -0
- data/Guardfile +16 -0
- data/Rakefile +2 -0
- data/lib/padrino-validation-html5.rb +2 -0
- data/lib/padrino/validation/html5.rb +68 -0
- data/lib/padrino/validation/html5/version.rb +7 -0
- data/padrino-validation-html5.gemspec +23 -0
- data/spec/padrino/validation/html5_spec.rb +51 -0
- data/spec/spec.rake +13 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/activemodel_base.rb +10 -0
- data/spec/support/matchers/have_tag.rb +93 -0
- metadata +125 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'spork' do
|
5
|
+
watch('Gemfile')
|
6
|
+
watch('Gemfile.lock')
|
7
|
+
watch('spec/spec_helper.rb')
|
8
|
+
end
|
9
|
+
|
10
|
+
guard 'rspec', :version => 2 do
|
11
|
+
watch(%r{^spec/.+_spec\.rb$})
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('spec/spec_helper.rb') { "spec" }
|
15
|
+
end
|
16
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "padrino-helpers/tag_helpers"
|
4
|
+
require "padrino-helpers/form_helpers"
|
5
|
+
require "padrino-helpers/form_builder/abstract_form_builder"
|
6
|
+
|
7
|
+
module Padrino
|
8
|
+
module Validation; end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Padrino::Validation::HTML5
|
12
|
+
module ExtendedHelpers
|
13
|
+
private
|
14
|
+
def identity_tag_attributes
|
15
|
+
super + [:readonly, :required, :autofocus, :novalidate, :formnovalidate, :multiple]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def registered(app)
|
21
|
+
builder = Padrino::Helpers::FormBuilder.const_get(app.settings.default_builder)
|
22
|
+
builder.send :include, self
|
23
|
+
Padrino::Helpers::TagHelpers.instance_eval do
|
24
|
+
alias_method :__identity_tag_attributes, :identity_tag_attributes
|
25
|
+
def identity_tag_attributes
|
26
|
+
__identity_tag_attributes + [:readonly, :required, :autofocus, :novalidate, :formnovalidate, :multiple]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def included(subj)
|
32
|
+
subj.field_types.each {|field|
|
33
|
+
define_method(field) {|field, options={}| options = inject_validations(field, options); super(field, options) }
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def inject_validations(field, options={})
|
39
|
+
validators = object.class.validators_on(field).
|
40
|
+
group_by(&:kind).
|
41
|
+
map {|kind, validators| [kind, validators.map(&:options).inject(&:merge)] }
|
42
|
+
validators.each do |kind, opts|
|
43
|
+
case kind
|
44
|
+
when :presence
|
45
|
+
options.reverse_merge!(required: true)
|
46
|
+
when :length
|
47
|
+
attrs = {}
|
48
|
+
if opts[:is]
|
49
|
+
attrs[:minlength] = attrs[:maxlength] = opts[:is]
|
50
|
+
else
|
51
|
+
attrs[:minlength] = [opts[:minimum], opts[:within].try(:first)].compact.max
|
52
|
+
attrs[:maxlength] = [opts[:maximum], opts[:within].try(:last)].compact.min
|
53
|
+
end
|
54
|
+
options.reverse_merge!(attrs.reject {|_, v| v.blank? })
|
55
|
+
when :inclusion
|
56
|
+
if opts[:in].respond_to?(:first) && opts[:in].respond_to?(:last)
|
57
|
+
attrs = {
|
58
|
+
min: opts[:in].first,
|
59
|
+
max: opts[:in].last
|
60
|
+
}
|
61
|
+
options.reverse_merge!(attrs.reject {|_, v| v.blank? })
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
options
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "padrino/validation/html5/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "padrino-validation-html5"
|
7
|
+
s.version = Padrino::Validation::HTML5::VERSION
|
8
|
+
s.authors = ["AOKI Hanae"]
|
9
|
+
s.email = ["aereal@kerare.org"]
|
10
|
+
s.homepage = "https://github.com/aereal/padrino-validation-html5"
|
11
|
+
s.summary = %q{automatically add client-side validations}
|
12
|
+
s.description = %q{automatically add client-side validations}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_runtime_dependency "padrino-helpers"
|
19
|
+
s.add_development_dependency "rake"
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "activemodel"
|
22
|
+
s.add_development_dependency "nokogiri"
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Padrino::Validation::HTML5 do
|
4
|
+
include Padrino::Helpers::OutputHelpers
|
5
|
+
include Padrino::Helpers::TagHelpers
|
6
|
+
include Padrino::Helpers::AssetTagHelpers
|
7
|
+
include Padrino::Helpers::FormHelpers
|
8
|
+
include Padrino::Validation::HTML5::ExtendedHelpers
|
9
|
+
|
10
|
+
before do
|
11
|
+
Padrino::Helpers::FormBuilder::StandardFormBuilder.send :include, Padrino::Validation::HTML5
|
12
|
+
class Model < ActiveModel::Base
|
13
|
+
@attrs = [:name, :age]
|
14
|
+
define_attribute_methods @attrs
|
15
|
+
attr_accessor *@attrs
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when model has field which should be present" do
|
20
|
+
before do
|
21
|
+
Model.validates_presence_of :name
|
22
|
+
end
|
23
|
+
|
24
|
+
it "injects `required' attribute to `input' element" do
|
25
|
+
form_for(Model.new, '/register') {|f| f.text_field :name }.
|
26
|
+
should have_tag('input', required: 'required')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when model has field which restricted max length" do
|
31
|
+
before do
|
32
|
+
Model.validates_length_of :name, maximum: 255
|
33
|
+
end
|
34
|
+
|
35
|
+
it "injects `maxlength' attribute to `input' element" do
|
36
|
+
form_for(Model.new, '/register') {|f| f.text_field :name }.
|
37
|
+
should have_tag('input', maxlength: '255')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when model has field which is inclusive of any range" do
|
42
|
+
before do
|
43
|
+
Model.validates_inclusion_of :age, in: 20..30
|
44
|
+
end
|
45
|
+
|
46
|
+
it "injects `max' attribute to element" do
|
47
|
+
form_for(Model.new, '/register') {|f| f.text_field :age }.
|
48
|
+
should have_tag('input', max: '30', min: '20')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec.rake
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
spec_tasks = Dir['spec/*/'].map { |d| File.basename(d) }
|
4
|
+
|
5
|
+
spec_tasks.each do |folder|
|
6
|
+
RSpec::Core::RakeTask.new("spec:#{folder}") do |t|
|
7
|
+
t.pattern = "./spec/#{folder}/**/*_spec.rb"
|
8
|
+
t.rspec_opts = %w(-fs --color)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run complete application spec suite"
|
13
|
+
task 'spec' => spec_tasks.map { |f| "spec:#{f}" }
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'spork'
|
5
|
+
|
6
|
+
Spork.prefork do
|
7
|
+
require "bundler/setup"
|
8
|
+
Bundler.setup(:default)
|
9
|
+
require "rspec"
|
10
|
+
require "nokogiri"
|
11
|
+
require "active_model"
|
12
|
+
require "padrino-helpers"
|
13
|
+
require "padrino/validation/html5"
|
14
|
+
|
15
|
+
pwd = File.dirname(__FILE__)
|
16
|
+
$: << File.expand_path(pwd + '/../lib')
|
17
|
+
|
18
|
+
Dir["#{pwd}/support/**/*.rb"].each {|_| require File.expand_path(_) }
|
19
|
+
end
|
20
|
+
|
21
|
+
Spork.each_run do
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_tag do |expected_tag, options={}|
|
4
|
+
match do |actual|
|
5
|
+
@expected_tag = expected_tag
|
6
|
+
@options = options
|
7
|
+
matched = nokogiri(actual)
|
8
|
+
|
9
|
+
if options[:count]
|
10
|
+
matched.size == options[:count].to_i
|
11
|
+
else
|
12
|
+
matched.any?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
failure_message_for_should do |actual|
|
17
|
+
"expected following output to contain a #{tag_inspect} tag:\n#{@document}"
|
18
|
+
end
|
19
|
+
|
20
|
+
failure_message_for_should_not do |actual|
|
21
|
+
"expected following output to omit a #{tag_inspect}:\n#{@document}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def nokogiri(str)
|
25
|
+
q = Nokogiri::CSS.parse(@expected_tag.to_s).map(&:to_xpath).first
|
26
|
+
@query = Nokogiri::XML::NodeSet === str ? q.gsub(%r|^//|, './/') : q
|
27
|
+
|
28
|
+
add_options_conditions_to!(@query)
|
29
|
+
|
30
|
+
@document =
|
31
|
+
case str
|
32
|
+
when Nokogiri::HTML::Document, Nokogiri::XML::NodeSet
|
33
|
+
str
|
34
|
+
when str.respond_to?(:body)
|
35
|
+
Nokogiri::HTML(str.body.to_s)
|
36
|
+
else
|
37
|
+
Nokogiri::HTML(str.to_s)
|
38
|
+
end
|
39
|
+
@document.xpath(*@query)
|
40
|
+
end
|
41
|
+
|
42
|
+
def xpath_escape(str)
|
43
|
+
if str.include?("'")
|
44
|
+
if str.include?('"')
|
45
|
+
parts = str.split("'").map {|part| "'#{part}'" }
|
46
|
+
"concat(#{parts.join(%|, "'", |)})"
|
47
|
+
else
|
48
|
+
%|"#{str}"|
|
49
|
+
end
|
50
|
+
else
|
51
|
+
"'#{str}'"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def tag_inspect
|
56
|
+
html = "<#{@expected_tag}"
|
57
|
+
|
58
|
+
@options.reject {|k, v| [:content, :count].include? k }.each do |k, v|
|
59
|
+
html << %| #{k}="#{v}"|
|
60
|
+
end
|
61
|
+
|
62
|
+
if @options[:content]
|
63
|
+
html << ">#{@options[:content]}</#{@expected_tag}>"
|
64
|
+
else
|
65
|
+
html << "/>"
|
66
|
+
end
|
67
|
+
|
68
|
+
html
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_attributes_conditions_to!(query)
|
72
|
+
attribute_conditions = []
|
73
|
+
|
74
|
+
@options.reject {|k, v| [:content, :count].include? k }.each do |k, v|
|
75
|
+
attribute_conditions << "@#{k} = #{xpath_escape(v)}"
|
76
|
+
end
|
77
|
+
|
78
|
+
unless attribute_conditions.none?
|
79
|
+
query << "[#{attribute_conditions.join(' and ')}]"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_content_condition_to!(query)
|
84
|
+
if @options[:content]
|
85
|
+
query << "[contains(., #{xpath_escape(@options[:content])})]"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_options_conditions_to!(query)
|
90
|
+
add_attributes_conditions_to!(query)
|
91
|
+
add_content_condition_to!(query)
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: padrino-validation-html5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- AOKI Hanae
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-10 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: padrino-helpers
|
16
|
+
requirement: &70152662705860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70152662705860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70152662705400 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70152662705400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70152662704840 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70152662704840
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: activemodel
|
49
|
+
requirement: &70152662704400 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70152662704400
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: nokogiri
|
60
|
+
requirement: &70152662703940 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70152662703940
|
69
|
+
description: automatically add client-side validations
|
70
|
+
email:
|
71
|
+
- aereal@kerare.org
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- Gemfile
|
79
|
+
- Guardfile
|
80
|
+
- Rakefile
|
81
|
+
- lib/padrino-validation-html5.rb
|
82
|
+
- lib/padrino/validation/html5.rb
|
83
|
+
- lib/padrino/validation/html5/version.rb
|
84
|
+
- padrino-validation-html5.gemspec
|
85
|
+
- spec/padrino/validation/html5_spec.rb
|
86
|
+
- spec/spec.rake
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
- spec/support/activemodel_base.rb
|
89
|
+
- spec/support/matchers/have_tag.rb
|
90
|
+
homepage: https://github.com/aereal/padrino-validation-html5
|
91
|
+
licenses: []
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
hash: 3227414695813390310
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
hash: 3227414695813390310
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 1.8.11
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: automatically add client-side validations
|
120
|
+
test_files:
|
121
|
+
- spec/padrino/validation/html5_spec.rb
|
122
|
+
- spec/spec.rake
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
- spec/support/activemodel_base.rb
|
125
|
+
- spec/support/matchers/have_tag.rb
|