hungryform 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -1
  3. data/.rspec +0 -1
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/README.md +72 -43
  7. data/Rakefile +3 -4
  8. data/hungryform.gemspec +4 -4
  9. data/lib/hungryform/configuration.rb +31 -0
  10. data/lib/hungryform/elements/base/active_element.rb +44 -36
  11. data/lib/hungryform/elements/base/element.rb +40 -49
  12. data/lib/hungryform/elements/base/group.rb +74 -71
  13. data/lib/hungryform/elements/base/hashable.rb +32 -30
  14. data/lib/hungryform/elements/base/options_element.rb +28 -24
  15. data/lib/hungryform/elements/html.rb +1 -1
  16. data/lib/hungryform/elements/page.rb +4 -0
  17. data/lib/hungryform/elements/radio_group.rb +1 -1
  18. data/lib/hungryform/elements/select_field.rb +14 -18
  19. data/lib/hungryform/elements/{text_area_field.rb → text_area.rb} +1 -1
  20. data/lib/hungryform/elements.rb +9 -1
  21. data/lib/hungryform/exceptions.rb +3 -0
  22. data/lib/hungryform/form.rb +32 -2
  23. data/lib/hungryform/resolver.rb +14 -16
  24. data/lib/hungryform/version.rb +1 -1
  25. data/lib/hungryform.rb +22 -5
  26. data/spec/elements/group_spec.rb +10 -1
  27. data/spec/elements/html_spec.rb +11 -9
  28. data/spec/elements/page_spec.rb +10 -7
  29. data/spec/elements/radio_group_spec.rb +9 -15
  30. data/spec/elements/select_field_spec.rb +19 -33
  31. data/spec/elements/shared_examples/active_element.rb +52 -0
  32. data/spec/elements/shared_examples/element.rb +42 -0
  33. data/spec/elements/shared_examples/group.rb +31 -0
  34. data/spec/elements/shared_examples/options_element.rb +24 -0
  35. data/spec/elements/text_area_spec.rb +14 -0
  36. data/spec/elements/text_field_spec.rb +10 -3
  37. data/spec/form_spec.rb +68 -1
  38. data/spec/resolver_spec.rb +7 -7
  39. data/spec/spec_helper.rb +4 -2
  40. metadata +29 -40
  41. data/Gemfile.lock +0 -52
  42. data/spec/elements/text_area_field_spec.rb +0 -7
  43. data/spec/support/shared_active_element.rb +0 -65
  44. data/spec/support/shared_element.rb +0 -62
  45. data/spec/support/shared_group.rb +0 -42
  46. data/spec/support/shared_options_element.rb +0 -36
@@ -1,37 +1,39 @@
1
1
  module HungryForm
2
- module Elements::Base
3
- # This module adds hashing capabilities to form elements.
4
- # Do not include this module in your classes. It is already
5
- # included in the base_element class.
6
- #
7
- # Sample usage:
8
- #
9
- # class MyField
10
- # attr_accessor :param1, :param2
11
- # hashable :param1, :param2
12
- # ...
13
- # end
14
- #
15
- # Any instance of MyField class will have the "to_hash" method
16
- # that will contain only the accessor/reader params defined in
17
- # the hashable macro.
18
- module Hashable
19
- def self.included(base)
20
- base.extend ClassMethods
21
- base.class_attribute :hashable_attributes
22
- base.hashable_attributes = []
23
- end
2
+ module Elements
3
+ module Base
4
+ # This module adds hashing capabilities to form elements.
5
+ # Do not include this module in your classes. It is already
6
+ # included in the base_element class.
7
+ #
8
+ # Sample usage:
9
+ #
10
+ # class MyField
11
+ # attr_accessor :param1, :param2
12
+ # hashable :param1, :param2
13
+ # ...
14
+ # end
15
+ #
16
+ # Any instance of MyField class will have the "to_hash" method
17
+ # that will contain only the accessor/reader params defined in
18
+ # the hashable macro.
19
+ module Hashable
20
+ def self.included(base)
21
+ base.extend ClassMethods
22
+ base.class_attribute :hashable_attributes
23
+ base.hashable_attributes = []
24
+ end
24
25
 
25
- def to_hash
26
- hash = self.class.hashable_attributes.each_with_object({}) do |param, h|
27
- h[param] = send(param) unless send(param).nil?
26
+ def to_hash
27
+ hash = self.class.hashable_attributes.each_with_object({}) do |param, h|
28
+ h[param] = send(param) unless send(param).nil?
29
+ end
30
+ hash.merge(_type: self.class.name.demodulize)
28
31
  end
29
- hash.merge(_type: self.class.name.demodulize)
30
- end
31
32
 
32
- module ClassMethods
33
- def hashable(*params)
34
- self.hashable_attributes = hashable_attributes.dup.concat params
33
+ module ClassMethods
34
+ def hashable(*params)
35
+ self.hashable_attributes = hashable_attributes.dup.concat params
36
+ end
35
37
  end
36
38
  end
37
39
  end
@@ -1,33 +1,37 @@
1
1
  module HungryForm
2
- module Elements::Base
3
- # The BaseOptionsElement class can be used as a base class for
4
- # fields with options, such as select or radio
5
- class OptionsElement < ActiveElement
6
- attr_accessor :options
2
+ module Elements
3
+ module Base
4
+ # The BaseOptionsElement class can be used as a base class for
5
+ # fields with options, such as select or radio
6
+ class OptionsElement < ActiveElement
7
+ attr_accessor :options
7
8
 
8
- hashable :options
9
+ hashable :options
9
10
 
10
- def initialize(name, parent, resolver, attributes = {}, &block)
11
- if attributes.key?(:options)
12
- self.options = attributes[:options].dup
13
- else
14
- fail HungryFormException, "No options provided for #{name}"
15
- end
11
+ def initialize(name, parent, resolver, attributes = {}, &block)
12
+ if attributes.key?(:options)
13
+ self.options = attributes.delete(:options)
14
+ else
15
+ fail HungryFormException, "No options provided for #{name}"
16
+ end
16
17
 
17
- unless options.is_a?(Hash)
18
- self.options = resolver.get_value(options, self)
19
- end
18
+ unless options.is_a?(Hash)
19
+ self.options = resolver.get_value(options, self)
20
+ end
20
21
 
21
- super
22
- end
22
+ self.options = ActiveSupport::HashWithIndifferentAccess.new(options)
23
+
24
+ super
25
+ end
23
26
 
24
- # Sets a value of the element
25
- # Checks the value from the resolver params against the available options
26
- def set_value
27
- if resolver.params.key?(name) && options.key?(resolver.params[name])
28
- self.value = resolver.params[name]
29
- else
30
- self.value = @attributes[:value]
27
+ # Sets a value of the element
28
+ # Checks the value from the resolver params against the available options
29
+ def set_value
30
+ if resolver.params.key?(name) && options.key?(resolver.params[name])
31
+ self.value = resolver.params[name]
32
+ else
33
+ self.value = attributes.delete(:value)
34
+ end
31
35
  end
32
36
  end
33
37
  end
@@ -6,7 +6,7 @@ module HungryForm
6
6
 
7
7
  def initialize(name, parent, resolver, attributes = {}, &block)
8
8
  super
9
- self.value = @attributes[:value] || ''
9
+ self.value = @attributes.delete(:value) || ''
10
10
  end
11
11
  end
12
12
  end
@@ -26,6 +26,10 @@ module HungryForm
26
26
  super
27
27
  self.title ||= label
28
28
  end
29
+
30
+ def to_s
31
+ self.name
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -9,7 +9,7 @@ module HungryForm
9
9
  self.value = resolver.params[name]
10
10
  end
11
11
  else
12
- self.value = @attributes[:value]
12
+ self.value = attributes.delete(:value)
13
13
  end
14
14
  end
15
15
  end
@@ -1,31 +1,27 @@
1
1
  module HungryForm
2
2
  module Elements
3
3
  class SelectField < Base::OptionsElement
4
- attr_accessor :multiple
5
- alias_method :multiple?, :multiple
6
-
7
- hashable :multiple
8
-
9
- def initialize(name, parent, resolver, attributes = {}, &block)
10
- self.multiple = attributes[:multiple] || false
11
- super
12
- end
13
-
14
4
  # Sets a value of the element
15
5
  # Checks the value from the resolver params against the available options
16
6
  def set_value
17
7
  if resolver.params.key?(name)
8
+ self.value = resolver.params[name] if acceptable_values?
9
+ else
10
+ self.value = attributes.delete(:value)
11
+ end
12
+ end
13
+
14
+ private
18
15
 
19
- # Check if all values present in the options
20
- if multiple?
21
- acceptable_values = (resolver.params[name] - options.keys).empty?
22
- else
23
- acceptable_values = options.keys.include?(resolver.params[name])
24
- end
16
+ # Check if all of the values from the resolver params are present
17
+ # in the options.
18
+ def acceptable_values?
19
+ options_sym_keys = options.keys.map(&:to_sym)
25
20
 
26
- self.value = resolver.params[name] if acceptable_values
21
+ if @attributes[:multiple] && resolver.params[name].respond_to?(:map)
22
+ (resolver.params[name].map(&:to_sym) - options_sym_keys).empty?
27
23
  else
28
- self.value = @attributes[:value]
24
+ options_sym_keys.include?(resolver.params[name].to_sym)
29
25
  end
30
26
  end
31
27
  end
@@ -1,6 +1,6 @@
1
1
  module HungryForm
2
2
  module Elements
3
- class TextAreaField < Base::ActiveElement
3
+ class TextArea < Base::ActiveElement
4
4
  end
5
5
  end
6
6
  end
@@ -1,5 +1,13 @@
1
1
  module HungryForm
2
2
  module Elements
3
+ # Find a class of the Elements module by name
4
+ def self.find_class(name)
5
+ constants.find { |c| Class === const_get(c) && c.to_s.underscore.to_sym == name }
6
+ end
7
+
8
+ def self.all_classes
9
+ constants.select { |c| Class === const_get(c) }
10
+ end
3
11
  end
4
12
  end
5
13
 
@@ -13,5 +21,5 @@ require_relative 'elements/group'
13
21
  require_relative 'elements/html'
14
22
  require_relative 'elements/text_field'
15
23
  require_relative 'elements/select_field'
16
- require_relative 'elements/text_area_field'
24
+ require_relative 'elements/text_area'
17
25
  require_relative 'elements/radio_group'
@@ -0,0 +1,3 @@
1
+ module HungryForm
2
+ HungryFormException = Class.new(StandardError)
3
+ end
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
  require 'active_support/core_ext/string/inflections'
3
3
  require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/core_ext/hash/indifferent_access'
4
5
  require 'hungryform/version'
5
6
  require 'hungryform/resolver'
6
7
  require 'hungryform/validator'
@@ -32,7 +33,7 @@ module HungryForm
32
33
  # in the form.pages array. Pages without dependencies will be allways
33
34
  # resolved. The rest of the pages will be ignored.
34
35
  class Form
35
- attr_reader :pages
36
+ attr_reader :pages, :current_page
36
37
 
37
38
  def initialize(attributes = {}, &block)
38
39
  unless block_given?
@@ -43,6 +44,12 @@ module HungryForm
43
44
  @pages = []
44
45
 
45
46
  instance_eval(&block)
47
+
48
+ if @resolver.params[:page]
49
+ @current_page = pages.find { |p| p.name.to_s == @resolver.params[:page] }
50
+ end
51
+
52
+ @current_page ||= pages.first
46
53
  end
47
54
 
48
55
  # Create a form page
@@ -68,7 +75,7 @@ module HungryForm
68
75
  !valid?
69
76
  end
70
77
 
71
- # Get all the elements that the form consists of
78
+ # Get all the elements the form consists of
72
79
  def elements
73
80
  @resolver.elements
74
81
  end
@@ -82,5 +89,28 @@ module HungryForm
82
89
  def to_json
83
90
  JSON.generate(to_hash)
84
91
  end
92
+
93
+ # Create a hash of form elements values
94
+ def values
95
+ active_elements = elements.select do |name, el|
96
+ el.is_a? Elements::Base::ActiveElement
97
+ end
98
+
99
+ active_elements.each_with_object({}) do |(name, el), o|
100
+ o[name.to_sym] = el.value
101
+ end
102
+ end
103
+
104
+ def next_page
105
+ pages.each_cons(2) do |page, next_page|
106
+ return next_page if page == current_page
107
+ end
108
+ end
109
+
110
+ def prev_page
111
+ pages.each_cons(2) do |prev_page, page|
112
+ return prev_page if page == current_page
113
+ end
114
+ end
85
115
  end
86
116
  end
@@ -5,8 +5,9 @@ module HungryForm
5
5
  attr_accessor :elements, :params
6
6
 
7
7
  def initialize(options = {})
8
- @params = options[:params] || {}
9
- @elements = {}
8
+ self.params = ActiveSupport::HashWithIndifferentAccess.new(options[:params] || {})
9
+
10
+ self.elements = {}
10
11
  end
11
12
 
12
13
  # Gets element value by element's name.
@@ -26,22 +27,19 @@ module HungryForm
26
27
  # we get its placeholders and replace substrings in the name argument
27
28
  element.placeholders.each { |k, v| name[k] &&= v } if element
28
29
 
29
- return @elements[name].value if @elements.key?(name)
30
- return @params[name] if @params.key?(name)
31
-
32
- name
30
+ elements[name].try(:value) || params[name] || name
33
31
  end
34
32
 
35
33
  # Gets dependency rules hash and returns true or false depending on
36
34
  # the result of a recursive processing of the rules
37
35
  def resolve_dependency(dependency)
38
36
  dependency.each do |operator, arguments|
37
+ operator = operator.to_sym
38
+
39
39
  case operator
40
- when 'AND'
41
- return resolve_multi_dependency(:and, arguments)
42
- when 'OR'
43
- return resolve_multi_dependency(:or, arguments)
44
- when 'NOT'
40
+ when :and, :or
41
+ return resolve_multi_dependency(operator, arguments)
42
+ when :not
45
43
  return !resolve_dependency(arguments)
46
44
  end
47
45
 
@@ -51,13 +49,13 @@ module HungryForm
51
49
  return false if arguments.any?(&:nil?)
52
50
 
53
51
  case operator
54
- when 'EQ'
52
+ when :eq
55
53
  return arguments[0].to_s == arguments[1].to_s
56
- when 'LT'
54
+ when :lt
57
55
  return arguments[0].to_f < arguments[1].to_f
58
- when 'GT'
56
+ when :gt
59
57
  return arguments[0].to_f > arguments[1].to_f
60
- when 'SET'
58
+ when :set
61
59
  return !arguments[0].empty?
62
60
  end
63
61
  end
@@ -65,7 +63,7 @@ module HungryForm
65
63
 
66
64
  private
67
65
 
68
- # Helper method to resolve AND or OR conditions.
66
+ # Method resolves AND or OR conditions.
69
67
  # Walks through the arguments and resolves their dependencies.
70
68
  def resolve_multi_dependency(type, arguments)
71
69
  if arguments.size == 0
@@ -1,3 +1,3 @@
1
1
  module HungryForm
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.6"
3
3
  end
data/lib/hungryform.rb CHANGED
@@ -1,12 +1,29 @@
1
+ module HungryForm
2
+ class << self
3
+ attr_writer :configuration
4
+
5
+ def configuration
6
+ @configuration ||= Configuration.new
7
+ end
8
+
9
+ def configure
10
+ yield(configuration)
11
+ end
12
+
13
+ def reset_config
14
+ @configuration = Configuration.new
15
+ end
16
+ end
17
+ end
18
+
1
19
  require 'json'
2
20
  require 'active_support/core_ext/string/inflections'
3
21
  require 'active_support/core_ext/class/attribute'
22
+ require 'active_support/core_ext/object'
4
23
  require 'hungryform/version'
5
24
  require 'hungryform/form'
25
+ require 'hungryform/exceptions'
6
26
  require 'hungryform/resolver'
27
+ require 'hungryform/configuration'
7
28
  require 'hungryform/validator'
8
- require 'hungryform/elements'
9
-
10
- module HungryForm
11
- HungryFormException = Class.new(StandardError)
12
- end
29
+ require 'hungryform/elements'
@@ -1,5 +1,14 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe HungryForm::Elements::Group do
4
- it_behaves_like "a group"
4
+ let(:resolver_options) { {} }
5
+ let(:resolver) { HungryForm::Resolver.new(resolver_options) }
6
+ let(:group_options) { {} }
7
+ let(:group) { HungryForm::Elements::Group.new(:parent_name, nil, resolver, group_options) {} }
8
+ let(:options) { {} }
9
+
10
+ subject { HungryForm::Elements::Group.new(:element_name, group, resolver, options) {} }
11
+
12
+ it_behaves_like 'an element'
13
+ it_behaves_like 'a group'
5
14
  end
@@ -1,17 +1,19 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe HungryForm::Elements::Html do
4
- it_behaves_like "an element" do
5
- let(:element_options) { {} }
6
- end
4
+ let(:resolver_options) { {} }
5
+ let(:resolver) { HungryForm::Resolver.new(resolver_options) }
6
+ let(:group_options) { {} }
7
+ let(:group) { HungryForm::Elements::Group.new(:group, nil, resolver, group_options) {} }
8
+ let(:options) { { value: 'body text' } }
9
+
10
+ subject { HungryForm::Elements::Html.new(:element_name, nil, resolver, options) {} }
7
11
 
8
- let(:resolver) { HungryForm::Resolver.new() }
9
- let(:options) { {value: "body text"} }
10
- subject { HungryForm::Elements::Html.new(:html, nil, resolver, options) {} }
12
+ it_behaves_like 'an element'
11
13
 
12
- describe ".new" do
13
- it "should have a value" do
14
- expect(subject.value).to eq "body text"
14
+ describe '.new' do
15
+ it 'should have a value' do
16
+ expect(subject.value).to eq 'body text'
15
17
  end
16
18
  end
17
19
  end
@@ -1,25 +1,28 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe HungryForm::Elements::Page do
4
- let(:resolver) { HungryForm::Resolver.new() }
4
+ let(:resolver_options) { {} }
5
+ let(:resolver) { HungryForm::Resolver.new(resolver_options) }
6
+
5
7
  let(:options) { {} }
6
- let(:page) { HungryForm::Elements::Page.new(:pagename, nil, resolver, options) {} }
8
+ subject { HungryForm::Elements::Page.new(:element_name, nil, resolver, options) {} }
7
9
 
8
- it_behaves_like "a group"
10
+ it_behaves_like 'an element'
11
+ it_behaves_like 'a group'
9
12
 
10
13
  describe ".new" do
11
14
  it "should have one element" do
12
- page = HungryForm::Elements::Page.new(:pagename, nil, resolver, options) do
15
+ subject = HungryForm::Elements::Page.new(:element_name, nil, resolver, options) do
13
16
  html :html_name, value: "<p>Test html block</p>"
14
17
  end
15
- expect(page.elements.size).to eq 1
18
+ expect(subject.elements.size).to eq 1
16
19
  end
17
20
  end
18
21
 
19
22
  describe "#group" do
20
23
  it "should contain a group" do
21
- page.group(:group_name, {}) {}
22
- expect(page.elements.first.class).to eq HungryForm::Elements::Group
24
+ subject.group(:group_name, {}) {}
25
+ expect(subject.elements.first.class).to eq HungryForm::Elements::Group
23
26
  end
24
27
  end
25
28
  end
@@ -3,27 +3,21 @@ require "spec_helper"
3
3
  describe HungryForm::Elements::RadioGroup do
4
4
  let(:resolver_options) { {} }
5
5
  let(:resolver) { HungryForm::Resolver.new(resolver_options) }
6
- let(:group) { HungryForm::Elements::Group.new(:group, nil, resolver, {}) {} }
6
+ let(:group_options) { {} }
7
+ let(:group) { HungryForm::Elements::Group.new(:group, nil, resolver, group_options) {} }
7
8
 
8
- let(:element_options) do
9
+ let(:options) do
9
10
  {
10
11
  :options => {
11
12
  "1" => "First",
12
- "2" => "Second",
13
- "3" => "Third"
13
+ "element_value" => "Second" # element_value is checked in shared_active_element
14
14
  }
15
15
  }
16
16
  end
17
- subject { HungryForm::Elements::RadioGroup.new(:element_name, group, resolver, element_options) {} }
18
17
 
19
- it_behaves_like "an element with options" do
20
- let(:options_element_options) do
21
- {
22
- :options => {
23
- "1" => "First",
24
- "element_value" => "Second" # element_value is checked in shared_active_element
25
- }
26
- }
27
- end
28
- end
18
+ subject { HungryForm::Elements::RadioGroup.new(:element_name, group, resolver, options) {} }
19
+
20
+ it_behaves_like 'an element'
21
+ it_behaves_like 'an active element'
22
+ it_behaves_like 'an element with options'
29
23
  end
@@ -3,45 +3,31 @@ require "spec_helper"
3
3
  describe HungryForm::Elements::SelectField do
4
4
  let(:resolver_options) { {} }
5
5
  let(:resolver) { HungryForm::Resolver.new(resolver_options) }
6
-
7
6
  let(:group_options) { {} }
8
7
  let(:group) { HungryForm::Elements::Group.new(:group, nil, resolver, group_options) {} }
9
8
 
10
- let(:element_options) do
11
- {
12
- :options => {
13
- "1" => "First",
14
- "2" => "Second",
15
- "3" => "Third"
16
- }
17
- }
18
- end
19
- subject { HungryForm::Elements::SelectField.new(:element_name, group, resolver, element_options) {} }
9
+ let(:options) do
10
+ {
11
+ :options => {
12
+ '1' => 'First',
13
+ 'element_value' => 'Second' # element_value is checked in shared_active_element
14
+ }
15
+ }
16
+ end
20
17
 
21
- it_behaves_like "an element with options" do
22
- let(:options_element_options) do
23
- {
24
- :options => {
25
- "1" => "First",
26
- "element_value" => "Second" # element_value is checked in shared_active_element
27
- }
28
- }
29
- end
30
- end
18
+ subject { HungryForm::Elements::SelectField.new(:element_name, group, resolver, options) {} }
31
19
 
32
- describe "#set_value" do
33
- context "when multiple enabled" do
34
- it "assigns multiple values" do
35
- resolver_options[:params] = {"group_element_name" => ["1", "2", "3"]}
36
- element_options[:multiple] = true
37
- expect(subject.value).to eq(["1", "2", "3"])
20
+ it_behaves_like 'an element'
21
+ it_behaves_like 'an active element'
22
+ it_behaves_like 'an element with options'
23
+
24
+ describe '#set_value' do
25
+ context 'when multiple enabled' do
26
+ it 'assigns multiple values' do
27
+ resolver_options[:params] = {"group_element_name" => ["1", "element_value"]}
28
+ options[:multiple] = true
29
+ expect(subject.value).to eq(["1", "element_value"])
38
30
  end
39
31
  end
40
32
  end
41
-
42
- describe "#to_hash" do
43
- it "should include multiple" do
44
- expect(subject.to_hash).to include(:multiple)
45
- end
46
- end
47
33
  end
@@ -0,0 +1,52 @@
1
+ RSpec.shared_examples "an active element" do
2
+ describe ".new" do
3
+ it "should have empty error" do
4
+ expect(subject.error).to eq ""
5
+ end
6
+
7
+ it "should not be required if its parent is not visible" do
8
+ group_options[:visible] = false
9
+ options[:required] = true
10
+ expect(subject.required?).to eq false
11
+ end
12
+
13
+ it "should have a nil value" do
14
+ expect(subject.value).to be nil
15
+ end
16
+
17
+ it "should have a value from form params" do
18
+ resolver_options[:params]= {"group_element_name" => "element_value" }
19
+ expect(subject.value).to eq "element_value"
20
+ end
21
+
22
+ it "should have a value from element structure" do
23
+ options[:value] = "element_value"
24
+ expect(subject.value).to eq "element_value"
25
+ end
26
+ end
27
+
28
+ describe "#valid?" do
29
+ context "when required" do
30
+ before(:each) { options[:required] = true }
31
+
32
+ it "is valid" do
33
+ subject.value = "value"
34
+ expect(subject.valid?).to eq true
35
+ expect(subject.error).to eq ''
36
+ end
37
+
38
+ it "is invalid" do
39
+ subject.value = ''
40
+ expect(subject.valid?).to eq false
41
+ expect(subject.error).to eq 'This field is required'
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#to_hash" do
47
+ it 'should include required, value and error' do
48
+ options.merge!(value: '', required: true)
49
+ expect(subject.to_hash).to include(:required, :value, :error)
50
+ end
51
+ end
52
+ end