hungryform 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/.gitignore +0 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +46 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/hungryform.gemspec +26 -0
- data/lib/hungryform/elements/base_active_element.rb +38 -0
- data/lib/hungryform/elements/base_element.rb +22 -0
- data/lib/hungryform/elements/base_group.rb +81 -0
- data/lib/hungryform/elements/group.rb +8 -0
- data/lib/hungryform/elements/html.rb +4 -0
- data/lib/hungryform/elements/page.rb +27 -0
- data/lib/hungryform/elements/text_field.rb +4 -0
- data/lib/hungryform/elements.rb +7 -0
- data/lib/hungryform/resolver.rb +79 -0
- data/lib/hungryform/validator.rb +13 -0
- data/lib/hungryform/version.rb +3 -0
- data/lib/hungryform.rb +63 -0
- data/spec/elements/group_spec.rb +5 -0
- data/spec/elements/html_spec.rb +16 -0
- data/spec/elements/page_spec.rb +25 -0
- data/spec/elements/text_field_spec.rb +5 -0
- data/spec/hungryform_spec.rb +27 -0
- data/spec/resolver_spec.rb +66 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/shared_active_element.rb +41 -0
- data/spec/support/shared_element.rb +48 -0
- data/spec/support/shared_group.rb +34 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a3eb50bf1ab74b3a5540384c4985bdaa0320666
|
4
|
+
data.tar.gz: 97110432dcc56453c65f81b1df816fc8a4dd1019
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb6ca009dcf1d557b5485e76810dd2d3001debea174634e125de56ceccc797a3d84153b2fe51ade45082d3d79d393c5e23d82ad2c7b5f2876e696fcdbcfc79b6
|
7
|
+
data.tar.gz: b63768d3bca0af1a22b5c1845f80bd5fc770f77ced167cc4d42cf62f03f75cb972f9aaebd79a31ba8c72d50bd807b36bd425d17c8fc2b2a04cb5633b2c949669
|
data/.gitignore
ADDED
File without changes
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hungryform (0.0.1)
|
5
|
+
activesupport
|
6
|
+
hashie
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (4.1.6)
|
12
|
+
i18n (~> 0.6, >= 0.6.9)
|
13
|
+
json (~> 1.7, >= 1.7.7)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
thread_safe (~> 0.1)
|
16
|
+
tzinfo (~> 1.1)
|
17
|
+
diff-lcs (1.2.5)
|
18
|
+
hashie (3.3.1)
|
19
|
+
i18n (0.6.11)
|
20
|
+
json (1.8.1)
|
21
|
+
minitest (5.4.2)
|
22
|
+
rake (10.3.2)
|
23
|
+
rspec (3.1.0)
|
24
|
+
rspec-core (~> 3.1.0)
|
25
|
+
rspec-expectations (~> 3.1.0)
|
26
|
+
rspec-mocks (~> 3.1.0)
|
27
|
+
rspec-core (3.1.7)
|
28
|
+
rspec-support (~> 3.1.0)
|
29
|
+
rspec-expectations (3.1.2)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.1.0)
|
32
|
+
rspec-mocks (3.1.3)
|
33
|
+
rspec-support (~> 3.1.0)
|
34
|
+
rspec-support (3.1.2)
|
35
|
+
thread_safe (0.3.4)
|
36
|
+
tzinfo (1.2.2)
|
37
|
+
thread_safe (~> 0.1)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
bundler (~> 1.6)
|
44
|
+
hungryform!
|
45
|
+
rake
|
46
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Andrey
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# HungryForm
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'hungryform'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install hungryform
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/andrba/hungryform/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/hungryform.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hungryform/version'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "hungryform"
|
9
|
+
spec.version = HungryForm::VERSION
|
10
|
+
spec.authors = ["Andrey Bazhutkin"]
|
11
|
+
spec.email = ["andrey.bazhutkin@gmail.com"]
|
12
|
+
spec.summary = "A Ruby Library for working with multi page forms"
|
13
|
+
spec.homepage = "https://github.com/andrba/hungryform"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_dependency "activesupport"
|
25
|
+
spec.add_dependency "hashie", "~> 3.3"
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class HungryForm
|
2
|
+
class BaseActiveElement < BaseElement
|
3
|
+
attr_accessor :error
|
4
|
+
|
5
|
+
def initialize(name, parent, resolver, options = {}, &block)
|
6
|
+
super
|
7
|
+
self.error = ''
|
8
|
+
|
9
|
+
# Filter only the options that are present in the HungryForm::Validator singleton class
|
10
|
+
@validation_rules = options.select { |key, val| HungryForm::Validator.respond_to?(key) }
|
11
|
+
|
12
|
+
self.required = false unless parent.visible?
|
13
|
+
|
14
|
+
if options.has_key?(:params)
|
15
|
+
self.value = options[:params][self.name] || ''
|
16
|
+
else
|
17
|
+
self.value = ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
self.error = ''
|
23
|
+
|
24
|
+
return true if !visible?
|
25
|
+
|
26
|
+
is_valid = true
|
27
|
+
@validation_rules.each do |key, rule|
|
28
|
+
error = HungryForm::Validator.send(key, self, rule) || ''
|
29
|
+
unless error.empty?
|
30
|
+
is_valid = false
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
is_valid
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class HungryForm
|
2
|
+
class BaseElement < ::Hashie::Mash
|
3
|
+
attr_accessor :name, :placeholders, :resolver
|
4
|
+
|
5
|
+
def initialize(name, parent, resolver, options = {})
|
6
|
+
self.placeholders ||= {}
|
7
|
+
self.resolver = resolver
|
8
|
+
|
9
|
+
super(options)
|
10
|
+
|
11
|
+
self.visible = true unless self.key?(:visible)
|
12
|
+
self.visible &&= resolver.resolve_dependency(::JSON.parse(self.dependency)) if self.key?(:dependency)
|
13
|
+
self.name = (parent.nil?? "" : "#{parent.name}_") + resolver.get_value(name, self)
|
14
|
+
|
15
|
+
if self.key?(:label)
|
16
|
+
self.label = resolver.get_value(self.label, self)
|
17
|
+
else
|
18
|
+
self.label = resolver.get_value(name, self).humanize
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class HungryForm
|
2
|
+
# A base group object is used to handle nested elements.
|
3
|
+
# Nested element can be a regular BaseElement or BaseActiveElement, as well as a BaseGroup element.
|
4
|
+
#
|
5
|
+
# The following sample has three BaseGroup elements (page, group and nested group) that define a structure
|
6
|
+
# of a single form page
|
7
|
+
#
|
8
|
+
# page :about do
|
9
|
+
# group :about_yourself do
|
10
|
+
# html :about, value: "Tell us about yourself"
|
11
|
+
# group :address do
|
12
|
+
# text_field :street
|
13
|
+
# text_field :city
|
14
|
+
# end
|
15
|
+
# group :contact do
|
16
|
+
# text_field :phone
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Every group element except for a nested group is
|
22
|
+
class BaseGroup < BaseElement
|
23
|
+
attr_accessor :elements, :errors
|
24
|
+
|
25
|
+
def initialize(name, parent, resolver, options = {}, &block)
|
26
|
+
raise HungryFormException, 'No group structure block given' unless block_given?
|
27
|
+
|
28
|
+
super
|
29
|
+
|
30
|
+
self.name = parent.nil?? name : "#{parent.name}_#{name}"
|
31
|
+
self.elements = []
|
32
|
+
self.errors = {}
|
33
|
+
|
34
|
+
instance_eval(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def group(name, options = {}, &block)
|
38
|
+
elements << HungryForm::Group.new(name, self, @resolver, options, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Validates an entire group. If a group consists of nested groups
|
42
|
+
# they will be validated recursively
|
43
|
+
def valid?
|
44
|
+
errors.clear
|
45
|
+
is_valid = true
|
46
|
+
|
47
|
+
elements.each do |el|
|
48
|
+
if el.invalid?
|
49
|
+
is_valid = false
|
50
|
+
case el
|
51
|
+
when BaseActiveElement
|
52
|
+
errors[el.name] = el.error
|
53
|
+
when BaseGroupObject
|
54
|
+
errors.merge!(el.errors)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
is_valid
|
60
|
+
end
|
61
|
+
|
62
|
+
def invalid?
|
63
|
+
!valid?
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(name, *args, &block)
|
67
|
+
#Find a matching class
|
68
|
+
klass = HungryForm.constants.find {|c| Class === HungryForm.const_get(c) && c.to_s.underscore.to_sym == name}
|
69
|
+
return super if klass.nil?
|
70
|
+
|
71
|
+
# Create a new element based on a symbol provided and push it into the group elements array
|
72
|
+
element = HungryForm::const_get(klass).send(:new, *([args[0], self, @resolver, args[1..-1]].flatten), &block)
|
73
|
+
elements << element
|
74
|
+
|
75
|
+
#Resolver keeps a hash of all elements of the form
|
76
|
+
@resolver.elements[element.name] = element
|
77
|
+
|
78
|
+
element
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class HungryForm
|
2
|
+
# Page is a main element of a form.
|
3
|
+
# Each page can include a page structure, defined in the block
|
4
|
+
#
|
5
|
+
# A sample page could look like this:
|
6
|
+
# page :about do
|
7
|
+
# html :before, value: "Please fill out the following fields"
|
8
|
+
# text_field :first_name
|
9
|
+
# text_field :last_name
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# The only required argument of a page is its name.
|
13
|
+
# You can specify a title and a label in the options like this:
|
14
|
+
#
|
15
|
+
# page :about, title: "About me", label: "About"
|
16
|
+
#
|
17
|
+
# If there is no title or label specified, they will be created
|
18
|
+
# from the :name argument
|
19
|
+
class Page < BaseGroup
|
20
|
+
attr_accessor :title
|
21
|
+
|
22
|
+
def initialize(name, parent, resolver, options = {}, &block)
|
23
|
+
super
|
24
|
+
self.title = self.title || self.label
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require_relative 'elements/base_element'
|
2
|
+
require_relative 'elements/base_active_element'
|
3
|
+
require_relative 'elements/base_group'
|
4
|
+
require_relative 'elements/page'
|
5
|
+
require_relative 'elements/group'
|
6
|
+
require_relative 'elements/html'
|
7
|
+
require_relative 'elements/text_field'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class HungryForm
|
2
|
+
# The class is responsible for dependency resolving.
|
3
|
+
# It contains all form elements and params
|
4
|
+
class Resolver
|
5
|
+
attr_accessor :elements
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@params = options[:params] || {}
|
9
|
+
@elements = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Gets element value by element's name.
|
13
|
+
# If name is lambda - returns lambda's result
|
14
|
+
# If name is present in the resolvers' elements hash - returns element's value
|
15
|
+
# If name is present in the resolvers' params hash - returns params value
|
16
|
+
# Otherwise returns the argument without changes
|
17
|
+
def get_value(name, element = nil)
|
18
|
+
return name.call(element) if name.respond_to? :call
|
19
|
+
|
20
|
+
name = name.to_s.dup
|
21
|
+
|
22
|
+
# Apply placeholders to the name.
|
23
|
+
# A sample name string can look like this: page1_group[GROUP_NUMBER]_field
|
24
|
+
# where [GROUP_NUMBER] is a placeholder. When an element is present
|
25
|
+
# we get its placeholders and replace substrings in the name argument
|
26
|
+
if element
|
27
|
+
element.placeholders.each { |k, v| name[k] &&= v }
|
28
|
+
end
|
29
|
+
|
30
|
+
return @elements[name].value if @elements.has_key?(name)
|
31
|
+
return @params[name] if @params.has_key?(name)
|
32
|
+
|
33
|
+
name
|
34
|
+
end
|
35
|
+
|
36
|
+
# Gets dependency rules hash and returns true or false depending on
|
37
|
+
# the result of a recursive processing of the rules
|
38
|
+
def resolve_dependency(dependency)
|
39
|
+
dependency.each do |operator, arguments|
|
40
|
+
case operator
|
41
|
+
when 'AND'
|
42
|
+
raise HungryFormException, "No arguments for AND comparison: #{arguments}" if arguments.size == 0
|
43
|
+
|
44
|
+
arguments.each do |argument|
|
45
|
+
return false unless resolve_dependency(argument)
|
46
|
+
end
|
47
|
+
|
48
|
+
return true
|
49
|
+
when 'OR'
|
50
|
+
raise HungryFormException, "No arguments for OR comparison: #{arguments}" if arguments.size == 0
|
51
|
+
|
52
|
+
arguments.each do |argument|
|
53
|
+
return true if resolve_dependency(argument)
|
54
|
+
end
|
55
|
+
|
56
|
+
return false
|
57
|
+
when 'NOT'
|
58
|
+
return !resolve_dependency(arguments)
|
59
|
+
end
|
60
|
+
|
61
|
+
arguments = [arguments] unless arguments.is_a?(Array)
|
62
|
+
|
63
|
+
arguments = arguments[0..1].map {|name| get_value(name)}
|
64
|
+
return false if arguments.any?{ |arg| arg.nil? }
|
65
|
+
|
66
|
+
case operator
|
67
|
+
when 'EQ'
|
68
|
+
return arguments[0].to_s == arguments[1].to_s
|
69
|
+
when 'LT'
|
70
|
+
return arguments[0].to_f < arguments[1].to_f
|
71
|
+
when 'GT'
|
72
|
+
return arguments[0].to_f > arguments[1].to_f
|
73
|
+
when 'SET'
|
74
|
+
return !arguments[0].empty?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/hungryform.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/string/inflections'
|
3
|
+
require 'hashie'
|
4
|
+
require "hungryform/version"
|
5
|
+
require "hungryform/resolver"
|
6
|
+
require "hungryform/validator"
|
7
|
+
require "hungryform/elements"
|
8
|
+
|
9
|
+
# HungryForm is an object that manages form creation and validation.
|
10
|
+
# A sample object could look like this:
|
11
|
+
#
|
12
|
+
# form = HungryForm.new :params => params do
|
13
|
+
# page :about_yourself do
|
14
|
+
# text_field :first_name, :required => true
|
15
|
+
# text_field :last_name, :required => true
|
16
|
+
# checkbox :dog, label: "Do you have a dog?"
|
17
|
+
# end
|
18
|
+
# page :about_your_dog, visible: '{"SET": "about_yourself_dog"}' do
|
19
|
+
# text_field :name, :required
|
20
|
+
# text_area :what_can_it_do, label: "What can it do?"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# A form must contain only pages.
|
25
|
+
# Whenever a specific form error occurres inside the form it raises a HungryFormException
|
26
|
+
#
|
27
|
+
# When a new instance of a HungryForm is created, it uses options[:params] to
|
28
|
+
# build a structure of itself. The pages with dependencies, that resolve during this
|
29
|
+
# process will be included in the form.pages array. Pages without dependencies will be allways resolved.
|
30
|
+
# The rest of the pages will be ignored
|
31
|
+
class HungryForm
|
32
|
+
HungryFormException = Class.new(StandardError)
|
33
|
+
|
34
|
+
attr_reader :current_page, :pages
|
35
|
+
|
36
|
+
def initialize(options = {}, &block)
|
37
|
+
raise HungryFormException, 'No form structure block given' unless block_given?
|
38
|
+
@resolver = Resolver.new(options.slice(:params))
|
39
|
+
@pages = []
|
40
|
+
instance_eval(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create a form page
|
44
|
+
def page(name, options = {}, &block)
|
45
|
+
page = Page.new(name, nil, @resolver, options, &block)
|
46
|
+
pages << page if page.visible?
|
47
|
+
end
|
48
|
+
|
49
|
+
# Entire form validation. Loops through the form pages and validates each page
|
50
|
+
def valid?
|
51
|
+
is_valid = true
|
52
|
+
pages.each do |page|
|
53
|
+
#Loop through pages to get all errors
|
54
|
+
is_valid = false if page.invalid?
|
55
|
+
end
|
56
|
+
|
57
|
+
is_valid
|
58
|
+
end
|
59
|
+
|
60
|
+
def invalid?
|
61
|
+
!valid?
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HungryForm::Html do
|
4
|
+
it_behaves_like "an element"
|
5
|
+
|
6
|
+
describe ".new" do
|
7
|
+
let(:resolver) { HungryForm::Resolver.new() }
|
8
|
+
let(:options) { {value: "body text"} }
|
9
|
+
subject { HungryForm::Html.new(:html, nil, resolver, options) {} }
|
10
|
+
|
11
|
+
it "should have a value" do
|
12
|
+
expect(subject.value).to eq "body text"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HungryForm::Page do
|
4
|
+
let(:resolver) { HungryForm::Resolver.new() }
|
5
|
+
let(:options) { {} }
|
6
|
+
let(:page) { HungryForm::Page.new(:pagename, nil, resolver, options) {} }
|
7
|
+
|
8
|
+
it_behaves_like "a group"
|
9
|
+
|
10
|
+
describe ".new" do
|
11
|
+
it "should have one element" do
|
12
|
+
page = HungryForm::Page.new(:pagename, nil, resolver, options) do
|
13
|
+
html :html_name, value: "<p>Test html block</p>"
|
14
|
+
end
|
15
|
+
expect(page.elements.size).to eq 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#group" do
|
20
|
+
it "should contain a group" do
|
21
|
+
page.group(:group_name, {}) {}
|
22
|
+
expect(page.elements.first.class).to eq HungryForm::Group
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HungryForm do
|
4
|
+
describe ".new" do
|
5
|
+
subject(:form) { HungryForm.new {
|
6
|
+
page :first do
|
7
|
+
end
|
8
|
+
page :second, visible: false do
|
9
|
+
end
|
10
|
+
page :third do
|
11
|
+
end
|
12
|
+
} }
|
13
|
+
|
14
|
+
it "should contain 2 pages" do
|
15
|
+
expect(subject.pages.size).to eq 2
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#page" do
|
20
|
+
subject(:form) { HungryForm.new() {} }
|
21
|
+
|
22
|
+
it "should contain a page" do
|
23
|
+
form.page(:page_name, {}) {}
|
24
|
+
expect(form.pages.first.class).to eq HungryForm::Page
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HungryForm::Resolver do
|
4
|
+
let(:resolver_params) { {:params => {}} }
|
5
|
+
subject(:resolver) { HungryForm::Resolver.new(resolver_params) }
|
6
|
+
|
7
|
+
describe ".get_value" do
|
8
|
+
let(:element) { HungryForm::Html.new(:html_name, nil, resolver, { value: "value" }) {} }
|
9
|
+
|
10
|
+
it "should get value from lambda param" do
|
11
|
+
value = subject.get_value( ->(el){ "value" } )
|
12
|
+
expect(value).to eq "value"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should get value from a form element" do
|
16
|
+
subject.elements[element.name] = element
|
17
|
+
expect(subject.get_value("html_name")).to eq "value"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should get value from a form params" do
|
21
|
+
resolver_params[:params] = { "param1" => "param_value" }
|
22
|
+
expect(subject.get_value("param1")).to eq "param_value"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should get value that equals the name" do
|
26
|
+
expect(subject.get_value("name that doesn't exist")).to eq "name that doesn't exist"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".resolve_dependency" do
|
31
|
+
it "should resolve EQ dependency" do
|
32
|
+
dependency = { "EQ" => ["Text", "Text"] }
|
33
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should resolve LT dependency" do
|
37
|
+
dependency = { "LT" => ["0", "1"] }
|
38
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should resolve GT dependency" do
|
42
|
+
dependency = { "GT" => ["1", "0"] }
|
43
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should resolve SET dependency" do
|
47
|
+
dependency = { "SET" => "1" }
|
48
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should resolve AND dependency" do
|
52
|
+
dependency = { "AND" => [{"SET" => "1"}, {"SET" => "1"}] }
|
53
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should resolve OR dependency" do
|
57
|
+
dependency = { "OR" => [{"SET" => ""}, {"SET" => "1"}] }
|
58
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should resolve NOT dependency" do
|
62
|
+
dependency = { "NOT" => {"SET" => ""} }
|
63
|
+
expect(subject.resolve_dependency(dependency)).to eq true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
RSpec.shared_examples "an active element" do
|
2
|
+
let(:resolver) { HungryForm::Resolver.new() }
|
3
|
+
|
4
|
+
let(:group_options) { {} }
|
5
|
+
let(:group) { HungryForm::Group.new(:group, nil, resolver, group_options) {} }
|
6
|
+
|
7
|
+
let(:element_options) { {} }
|
8
|
+
let(:element) { described_class.new(:element_name, group, resolver, element_options) {} }
|
9
|
+
|
10
|
+
it_behaves_like "an element"
|
11
|
+
|
12
|
+
describe ".new" do
|
13
|
+
it "should have empty error" do
|
14
|
+
expect(element.error).to eq ""
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not be required if its parent is not visible" do
|
18
|
+
group_options[:visible] = false
|
19
|
+
element_options[:required] = true
|
20
|
+
expect(element.required?).to eq false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#valid?" do
|
25
|
+
describe "when required" do
|
26
|
+
before(:each) do
|
27
|
+
element_options[:required] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "is valid" do
|
31
|
+
element.value = "value"
|
32
|
+
expect(element.valid?).to eq true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "is invalid" do
|
36
|
+
element.value = ""
|
37
|
+
expect(element.valid?).to eq false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
RSpec.shared_examples "an element" do
|
2
|
+
let(:resolver) { HungryForm::Resolver.new() }
|
3
|
+
|
4
|
+
let(:group) { HungryForm::Group.new(:group, nil, resolver, {}) {} }
|
5
|
+
|
6
|
+
let(:element_options) { {} }
|
7
|
+
let(:element) { described_class.new(:element_name, group, resolver, element_options) {} }
|
8
|
+
|
9
|
+
describe "#visible?" do
|
10
|
+
it "should be visible" do
|
11
|
+
expect(element.visible?).to eq true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not be visible" do
|
15
|
+
element_options[:visible] = false
|
16
|
+
expect(element.visible?).to eq false
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when dependency is present" do
|
20
|
+
it "should not be visible" do
|
21
|
+
element_options[:dependency] = '{"EQ": ["0", "1"]}'
|
22
|
+
expect(element.visible?).to eq false
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should never be visible" do
|
26
|
+
element_options[:visible] = false
|
27
|
+
element_options[:dependency] = '{"EQ": ["1", "1"]}'
|
28
|
+
expect(element.visible?).to eq false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be visible" do
|
32
|
+
element_options[:dependency] = '{"EQ": ["1", "1"]}'
|
33
|
+
expect(element.visible?).to eq true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#label" do
|
39
|
+
it "should have a humanized label based on element's name" do
|
40
|
+
expect(element.label).to eq "Element name"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have a label defined in options" do
|
44
|
+
element_options[:label] = "Special Label"
|
45
|
+
expect(element.label).to eq "Special Label"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
RSpec.shared_examples "a group" do
|
2
|
+
let(:resolver) { HungryForm::Resolver.new() }
|
3
|
+
|
4
|
+
let(:page) { described_class.new(:parent_name, nil, resolver, {}) {} }
|
5
|
+
|
6
|
+
let(:group_options) { {} }
|
7
|
+
let(:group) { described_class.new(:name, page, resolver, group_options) {} }
|
8
|
+
|
9
|
+
it_behaves_like "an element"
|
10
|
+
|
11
|
+
describe "#group" do
|
12
|
+
it "creates a nested group" do
|
13
|
+
group.group(:nested, {}) {}
|
14
|
+
expect(group.elements.first.class).to eq HungryForm::Group
|
15
|
+
end
|
16
|
+
|
17
|
+
it "concatenates nested element's name with the parent's one" do
|
18
|
+
group.group(:nested, {}) {}
|
19
|
+
expect(group.elements.first.name).to eq "parent_name_name_nested"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".method_missing" do
|
24
|
+
it "creates a nested element" do
|
25
|
+
group.html(:name)
|
26
|
+
expect(group.elements.first.class).to eq HungryForm::Html
|
27
|
+
end
|
28
|
+
|
29
|
+
it "concatenates nested element's name with the parent's one" do
|
30
|
+
group.html(:html)
|
31
|
+
expect(group.elements.first.name).to eq "parent_name_name_html"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hungryform
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrey Bazhutkin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: hashie
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.3'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.3'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- andrey.bazhutkin@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- LICENSE
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- hungryform.gemspec
|
98
|
+
- lib/hungryform.rb
|
99
|
+
- lib/hungryform/elements.rb
|
100
|
+
- lib/hungryform/elements/base_active_element.rb
|
101
|
+
- lib/hungryform/elements/base_element.rb
|
102
|
+
- lib/hungryform/elements/base_group.rb
|
103
|
+
- lib/hungryform/elements/group.rb
|
104
|
+
- lib/hungryform/elements/html.rb
|
105
|
+
- lib/hungryform/elements/page.rb
|
106
|
+
- lib/hungryform/elements/text_field.rb
|
107
|
+
- lib/hungryform/resolver.rb
|
108
|
+
- lib/hungryform/validator.rb
|
109
|
+
- lib/hungryform/version.rb
|
110
|
+
- spec/elements/group_spec.rb
|
111
|
+
- spec/elements/html_spec.rb
|
112
|
+
- spec/elements/page_spec.rb
|
113
|
+
- spec/elements/text_field_spec.rb
|
114
|
+
- spec/hungryform_spec.rb
|
115
|
+
- spec/resolver_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- spec/support/shared_active_element.rb
|
118
|
+
- spec/support/shared_element.rb
|
119
|
+
- spec/support/shared_group.rb
|
120
|
+
homepage: https://github.com/andrba/hungryform
|
121
|
+
licenses:
|
122
|
+
- MIT
|
123
|
+
metadata: {}
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 2.4.4
|
141
|
+
signing_key:
|
142
|
+
specification_version: 4
|
143
|
+
summary: A Ruby Library for working with multi page forms
|
144
|
+
test_files:
|
145
|
+
- spec/elements/group_spec.rb
|
146
|
+
- spec/elements/html_spec.rb
|
147
|
+
- spec/elements/page_spec.rb
|
148
|
+
- spec/elements/text_field_spec.rb
|
149
|
+
- spec/hungryform_spec.rb
|
150
|
+
- spec/resolver_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
- spec/support/shared_active_element.rb
|
153
|
+
- spec/support/shared_element.rb
|
154
|
+
- spec/support/shared_group.rb
|