reactive-ruby 0.7.28 → 0.7.29
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 +4 -4
- data/.codeclimate.yml +6 -0
- data/Gemfile.lock +4 -1
- data/README.md +132 -68
- data/Rakefile +5 -2
- data/example/examples/Gemfile +0 -2
- data/example/rails-tutorial/Gemfile +3 -2
- data/lib/generators/reactive_ruby/test_app/templates/application.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/application.rb +2 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +3 -0
- data/lib/generators/reactive_ruby/test_app/templates/boot.rb +6 -0
- data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
- data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +105 -0
- data/lib/rails-helpers/top_level_rails_component.rb +9 -16
- data/lib/{reactive-ruby → react}/api.rb +8 -65
- data/lib/{reactive-ruby → react}/callbacks.rb +0 -0
- data/lib/react/component.rb +266 -0
- data/lib/react/component/api.rb +48 -0
- data/lib/react/component/class_methods.rb +183 -0
- data/lib/{reactive-ruby → react}/element.rb +10 -11
- data/lib/{reactive-ruby → react}/event.rb +0 -0
- data/lib/{reactive-ruby → react}/ext/hash.rb +0 -0
- data/lib/{reactive-ruby → react}/ext/string.rb +0 -0
- data/lib/react/native_library.rb +57 -0
- data/lib/{reactive-ruby → react}/observable.rb +0 -4
- data/lib/{reactive-ruby → react}/rendering_context.rb +0 -6
- data/lib/{reactive-ruby → react}/state.rb +3 -6
- data/lib/{reactive-ruby → react}/top_level.rb +2 -3
- data/lib/react/validator.rb +127 -0
- data/lib/reactive-ruby.rb +20 -20
- data/lib/reactive-ruby/version.rb +1 -1
- data/{opal-spec/reactjs → spec}/index.html.erb +1 -1
- data/{opal-spec → spec/react}/callbacks_spec.rb +8 -9
- data/{opal-spec → spec/react}/component_spec.rb +170 -120
- data/spec/react/dsl_spec.rb +16 -0
- data/{opal-spec → spec/react}/element_spec.rb +7 -20
- data/{opal-spec → spec/react}/event_spec.rb +3 -1
- data/spec/react/native_library_spec.rb +10 -0
- data/spec/react/param_declaration_spec.rb +18 -0
- data/{opal-spec → spec/react}/react_spec.rb +3 -2
- data/spec/react/react_state_spec.rb +22 -0
- data/spec/react/top_level_component_spec.rb +68 -0
- data/{opal-spec → spec/react}/tutorial/tutorial_spec.rb +11 -13
- data/{opal-spec → spec/react}/validator_spec.rb +50 -4
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +22 -4
- data/spec/spec_helper.rb +51 -0
- data/spec/support/react/spec_helpers.rb +57 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- metadata +56 -24
- data/lib/reactive-ruby/component.rb +0 -502
- data/lib/reactive-ruby/validator.rb +0 -99
- data/old-readme +0 -220
- data/opal-spec/spec_helper.rb +0 -29
@@ -0,0 +1,183 @@
|
|
1
|
+
module React
|
2
|
+
module Component
|
3
|
+
module ClassMethods
|
4
|
+
def backtrace(*args)
|
5
|
+
@backtrace_off = (args[0] == :off)
|
6
|
+
end
|
7
|
+
|
8
|
+
def process_exception(e, component, reraise = nil)
|
9
|
+
message = ["Exception raised while rendering #{component}"]
|
10
|
+
if !@backtrace_off
|
11
|
+
message << " #{e.backtrace[0]}"
|
12
|
+
message += e.backtrace[1..-1].collect { |line| line }
|
13
|
+
else
|
14
|
+
message[0] += ": #{e.message}"
|
15
|
+
end
|
16
|
+
message = message.join("\n")
|
17
|
+
`console.error(message)`
|
18
|
+
raise e if reraise
|
19
|
+
end
|
20
|
+
|
21
|
+
def validator
|
22
|
+
@validator ||= React::Validator.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def prop_types
|
26
|
+
if self.validator
|
27
|
+
{
|
28
|
+
_componentValidator: %x{
|
29
|
+
function(props, propName, componentName) {
|
30
|
+
var errors = #{validator.validate(Hash.new(`props`))};
|
31
|
+
var error = new Error(#{"In component `" + self.name + "`\n" + `errors`.join("\n")});
|
32
|
+
return #{`errors`.count > 0 ? `error` : `undefined`};
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
else
|
37
|
+
{}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_props
|
42
|
+
validator.default_props
|
43
|
+
end
|
44
|
+
|
45
|
+
def params(&block)
|
46
|
+
validator.build(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def define_param_method(name, param_type)
|
50
|
+
if param_type == React::Observable
|
51
|
+
(@two_way_params ||= []) << name
|
52
|
+
define_method("#{name}") do
|
53
|
+
params[name].instance_variable_get("@value") if params[name]
|
54
|
+
end
|
55
|
+
define_method("#{name}!") do |*args|
|
56
|
+
return unless params[name]
|
57
|
+
if args.count > 0
|
58
|
+
current_value = params[name].instance_variable_get("@value")
|
59
|
+
params[name].call args[0]
|
60
|
+
current_value
|
61
|
+
else
|
62
|
+
current_value = params[name].instance_variable_get("@value")
|
63
|
+
params[name].call current_value unless @dont_update_state rescue nil # rescue in case we in middle of render
|
64
|
+
params[name]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
elsif param_type == Proc
|
68
|
+
define_method("#{name}") do |*args, &block|
|
69
|
+
params[name].call(*args, &block) if params[name]
|
70
|
+
end
|
71
|
+
else
|
72
|
+
define_method("#{name}") do
|
73
|
+
@processed_params[name] ||= if param_type.respond_to? :_react_param_conversion
|
74
|
+
param_type._react_param_conversion params[name]
|
75
|
+
elsif param_type.is_a? Array and param_type[0].respond_to? :_react_param_conversion
|
76
|
+
params[name].collect { |param| param_type[0]._react_param_conversion param }
|
77
|
+
else
|
78
|
+
params[name]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def required_param(name, options = {})
|
85
|
+
validator.requires(name, options)
|
86
|
+
define_param_method(name, options[:type])
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :require_param, :required_param
|
90
|
+
|
91
|
+
def optional_param(name, options = {})
|
92
|
+
validator.optional(name, options)
|
93
|
+
define_param_method(name, options[:type]) unless name == :params
|
94
|
+
end
|
95
|
+
|
96
|
+
def collect_other_params_as(name)
|
97
|
+
validator.allow_undefined_props = true
|
98
|
+
define_method(name) do
|
99
|
+
@_all_others ||= self.class.validator.undefined_props(props)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def define_state(*states, &block)
|
104
|
+
default_initial_value = (block and block.arity == 0) ? yield : nil
|
105
|
+
states_hash = (states.last.is_a? Hash) ? states.pop : {}
|
106
|
+
states.each { |name| states_hash[name] = default_initial_value }
|
107
|
+
(self.initial_state ||= {}).merge! states_hash
|
108
|
+
states_hash.each do |name, initial_value|
|
109
|
+
define_state_methods(self, name, &block)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def export_state(*states, &block)
|
114
|
+
default_initial_value = (block and block.arity == 0) ? yield : nil
|
115
|
+
states_hash = (states.last.is_a? Hash) ? states.pop : {}
|
116
|
+
states.each { |name| states_hash[name] = default_initial_value }
|
117
|
+
React::State.initialize_states(self, states_hash)
|
118
|
+
states_hash.each do |name, initial_value|
|
119
|
+
define_state_methods(self, name, self, &block)
|
120
|
+
define_state_methods(singleton_class, name, self, &block)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def define_state_methods(this, name, from = nil, &block)
|
125
|
+
this.define_method("#{name}") do
|
126
|
+
React::State.get_state(from || self, name)
|
127
|
+
end
|
128
|
+
this.define_method("#{name}=") do |new_state|
|
129
|
+
yield name, React::State.get_state(from || self, name), new_state if block and block.arity > 0
|
130
|
+
React::State.set_state(from || self, name, new_state)
|
131
|
+
end
|
132
|
+
this.define_method("#{name}!") do |*args|
|
133
|
+
#return unless @native
|
134
|
+
if args.count > 0
|
135
|
+
yield name, React::State.get_state(from || self, name), args[0] if block and block.arity > 0
|
136
|
+
current_value = React::State.get_state(from || self, name)
|
137
|
+
React::State.set_state(from || self, name, args[0])
|
138
|
+
current_value
|
139
|
+
else
|
140
|
+
current_state = React::State.get_state(from || self, name)
|
141
|
+
yield name, React::State.get_state(from || self, name), current_state if block and block.arity > 0
|
142
|
+
React::State.set_state(from || self, name, current_state)
|
143
|
+
React::Observable.new(current_state) do |update|
|
144
|
+
yield name, React::State.get_state(from || self, name), update if block and block.arity > 0
|
145
|
+
React::State.set_state(from || self, name, update)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def native_mixin(item)
|
152
|
+
native_mixins << item
|
153
|
+
end
|
154
|
+
|
155
|
+
def native_mixins
|
156
|
+
@native_mixins ||= []
|
157
|
+
end
|
158
|
+
|
159
|
+
def static_call_back(name, &block)
|
160
|
+
static_call_backs[name] = block
|
161
|
+
end
|
162
|
+
|
163
|
+
def static_call_backs
|
164
|
+
@static_call_backs ||= {}
|
165
|
+
end
|
166
|
+
|
167
|
+
def export_component(opts = {})
|
168
|
+
export_name = (opts[:as] || name).split("::")
|
169
|
+
first_name = export_name.first
|
170
|
+
Native(`window`)[first_name] = add_item_to_tree(Native(`window`)[first_name], [React::API.create_native_react_class(self)] + export_name[1..-1].reverse).to_n
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_item_to_tree(current_tree, new_item)
|
174
|
+
if Native(current_tree).class != Native::Object or new_item.length == 1
|
175
|
+
new_item.inject do |memo, sub_name| {sub_name => memo} end
|
176
|
+
else
|
177
|
+
Native(current_tree)[new_item.last] = add_item_to_tree(Native(current_tree)[new_item.last], new_item[0..-2])
|
178
|
+
current_tree
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'react/ext/string'
|
2
2
|
|
3
3
|
module React
|
4
4
|
class Element
|
@@ -6,11 +6,11 @@ module React
|
|
6
6
|
|
7
7
|
alias_native :element_type, :type
|
8
8
|
alias_native :props, :props
|
9
|
-
|
9
|
+
|
10
10
|
attr_reader :type
|
11
11
|
attr_reader :properties
|
12
12
|
attr_reader :block
|
13
|
-
|
13
|
+
|
14
14
|
attr_accessor :waiting_on_resources
|
15
15
|
|
16
16
|
def initialize(native_element, type, properties, block)
|
@@ -39,22 +39,22 @@ module React
|
|
39
39
|
@properties.merge! props
|
40
40
|
self
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def render(props = {}) # for rendering children
|
44
44
|
if props.empty?
|
45
45
|
React::RenderingContext.render(self)
|
46
46
|
else
|
47
47
|
React::RenderingContext.render(
|
48
48
|
Element.new(
|
49
|
-
`React.cloneElement(#{self.to_n}, #{API.convert_props(props)})`,
|
50
|
-
type,
|
51
|
-
properties.merge(props),
|
49
|
+
`React.cloneElement(#{self.to_n}, #{API.convert_props(props)})`,
|
50
|
+
type,
|
51
|
+
properties.merge(props),
|
52
52
|
block
|
53
53
|
)
|
54
54
|
)
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def method_missing(class_name, args = {}, &new_block)
|
59
59
|
class_name = class_name.split("__").collect { |s| s.gsub("_", "-") }.join("_")
|
60
60
|
new_props = properties.dup
|
@@ -65,14 +65,13 @@ module React
|
|
65
65
|
React::RenderingContext.build { React::RenderingContext.render(type, new_props, &new_block) }
|
66
66
|
)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def as_node
|
70
70
|
RenderingContext.as_node(self)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def delete
|
74
74
|
RenderingContext.delete(self)
|
75
75
|
end
|
76
|
-
|
77
76
|
end
|
78
77
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module React
|
2
|
+
class NativeLibrary
|
3
|
+
def self.renames_and_exclusions
|
4
|
+
@renames_and_exclusions ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.libraries
|
8
|
+
@libraries ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.const_missing(name)
|
12
|
+
if renames_and_exclusions.has_key? name
|
13
|
+
if native_name = renames_and_exclusions[name]
|
14
|
+
native_name
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
else
|
19
|
+
libraries.each do |library|
|
20
|
+
native_name = "#{library}.#{name}"
|
21
|
+
native_component = `eval(#{native_name})` rescue nil
|
22
|
+
React::API.import_native_component(name, native_component) and return name if native_component and `native_component != undefined`
|
23
|
+
end
|
24
|
+
name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.method_missing(n, *args, &block)
|
29
|
+
name = n
|
30
|
+
if name =~ /_as_node$/
|
31
|
+
node_only = true
|
32
|
+
name = name.gsub(/_as_node$/, "")
|
33
|
+
end
|
34
|
+
unless name = const_get(name)
|
35
|
+
return super
|
36
|
+
end
|
37
|
+
if node_only
|
38
|
+
React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
|
39
|
+
else
|
40
|
+
React::RenderingContext.render(name, *args, &block)
|
41
|
+
end
|
42
|
+
rescue
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.imports(library)
|
46
|
+
libraries << library
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.rename(rename_list={})
|
50
|
+
renames_and_exclusions.merge!(rename_list.invert)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.exclude(*exclude_list)
|
54
|
+
renames_and_exclusions.merge(Hash[exclude_list.map {|k| [k, nil]}])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module React
|
2
|
-
|
3
2
|
class Observable
|
4
|
-
|
5
3
|
def initialize(value, on_change = nil, &block)
|
6
4
|
@value = value
|
7
5
|
@on_change = on_change || block
|
@@ -27,7 +25,5 @@ module React
|
|
27
25
|
def to_proc
|
28
26
|
lambda { |arg = @value| @on_change.call arg }
|
29
27
|
end
|
30
|
-
|
31
28
|
end
|
32
|
-
|
33
29
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module React
|
2
|
-
|
3
2
|
class RenderingContext
|
4
|
-
|
5
3
|
class << self
|
6
4
|
attr_accessor :waiting_on_resources
|
7
5
|
end
|
@@ -76,11 +74,9 @@ module React
|
|
76
74
|
value.as_node if value.is_a? Element rescue nil
|
77
75
|
end if args[0] and args[0].is_a? Hash
|
78
76
|
end
|
79
|
-
|
80
77
|
end
|
81
78
|
|
82
79
|
class ::Object
|
83
|
-
|
84
80
|
alias_method :old_method_missing, :method_missing
|
85
81
|
|
86
82
|
["span", "para", "td", "th", "while_loading"].each do |tag|
|
@@ -101,7 +97,5 @@ module React
|
|
101
97
|
return self.method_missing(*["br"]) if self.is_a? React::Component
|
102
98
|
React::RenderingContext.render("span") { React::RenderingContext.render(self.to_s); React::RenderingContext.render("br") }
|
103
99
|
end
|
104
|
-
|
105
100
|
end
|
106
|
-
|
107
101
|
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
module React
|
2
|
-
|
3
2
|
class State
|
4
|
-
|
5
3
|
class << self
|
6
|
-
|
7
4
|
attr_reader :current_observer
|
8
5
|
|
9
6
|
def initialize_states(object, initial_values) # initialize objects' name/value pairs
|
@@ -17,9 +14,12 @@ module React
|
|
17
14
|
end
|
18
15
|
|
19
16
|
def set_state2(object, name, value) # set object's name state to value, tell all observers it has changed. Observers must implement update_react_js_state
|
17
|
+
object_needs_notification = object.respond_to? :update_react_js_state
|
20
18
|
observers_by_name[object][name].dup.each do |observer|
|
21
19
|
observer.update_react_js_state(object, name, value)
|
20
|
+
object_needs_notification = false if object == observer
|
22
21
|
end
|
22
|
+
object.update_react_js_state(nil, name, value) if object_needs_notification
|
23
23
|
end
|
24
24
|
|
25
25
|
def set_state(object, name, value, delay=nil)
|
@@ -110,9 +110,6 @@ module React
|
|
110
110
|
def observers_by_name
|
111
111
|
@observers_by_name ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = [] } }
|
112
112
|
end
|
113
|
-
|
114
113
|
end
|
115
|
-
|
116
114
|
end
|
117
|
-
|
118
115
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "native"
|
2
2
|
require 'active_support'
|
3
|
-
require '
|
3
|
+
require 'react/component'
|
4
4
|
|
5
5
|
module React
|
6
6
|
HTML_TAGS = %w(a abbr address area article aside audio b base bdi bdo big blockquote body br
|
@@ -22,7 +22,7 @@ module React
|
|
22
22
|
readOnly rel required role rows rowSpan sandbox scope scrolling seamless
|
23
23
|
selected shape size sizes span spellCheck src srcDoc srcSet start step style
|
24
24
|
tabIndex target title type useMap value width wmode dangerouslySetInnerHTML)
|
25
|
-
|
25
|
+
|
26
26
|
def self.create_element(type, properties = {}, &block)
|
27
27
|
React::API.create_element(type, properties, &block)
|
28
28
|
end
|
@@ -49,5 +49,4 @@ module React
|
|
49
49
|
def self.unmount_component_at_node(node)
|
50
50
|
`React.unmountComponentAtNode(node.$$class ? node[0] : node)`
|
51
51
|
end
|
52
|
-
|
53
52
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module React
|
2
|
+
class Validator
|
3
|
+
attr_accessor :errors
|
4
|
+
private :errors
|
5
|
+
|
6
|
+
def self.build(&block)
|
7
|
+
self.new.build(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def build(&block)
|
11
|
+
instance_eval(&block)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def requires(name, options = {})
|
16
|
+
options[:required] = true
|
17
|
+
define_rule(name, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def optional(name, options = {})
|
21
|
+
options[:required] = false
|
22
|
+
define_rule(name, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def allow_undefined_props=(allow)
|
26
|
+
@allow_undefined_props = allow
|
27
|
+
end
|
28
|
+
|
29
|
+
def undefined_props(props)
|
30
|
+
self.allow_undefined_props = true
|
31
|
+
props.reject { |name, value| rules[name] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate(props)
|
35
|
+
self.errors = []
|
36
|
+
validate_undefined(props) unless allow_undefined_props?
|
37
|
+
props = coerce_native_hash_values(defined_props(props))
|
38
|
+
validate_required(props)
|
39
|
+
props.each do |name, value|
|
40
|
+
validate_types(name, value)
|
41
|
+
validate_allowed(name, value)
|
42
|
+
end
|
43
|
+
errors
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_props
|
47
|
+
rules
|
48
|
+
.select {|key, value| value.keys.include?("default") }
|
49
|
+
.inject({}) {|memo, (k,v)| memo[k] = v[:default]; memo}
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def defined_props(props)
|
55
|
+
props.select { |name| rules.keys.include?(name) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def allow_undefined_props?
|
59
|
+
!!@allow_undefined_props
|
60
|
+
end
|
61
|
+
|
62
|
+
def rules
|
63
|
+
@rules ||= { children: { required: false } }
|
64
|
+
end
|
65
|
+
|
66
|
+
def define_rule(name, options = {})
|
67
|
+
rules[name] = coerce_native_hash_values(options)
|
68
|
+
end
|
69
|
+
|
70
|
+
def errors
|
71
|
+
@errors ||= []
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_types(prop_name, value)
|
75
|
+
return unless klass = rules[prop_name][:type]
|
76
|
+
if klass.is_a?(Array) && klass.length > 0
|
77
|
+
validate_value_array(prop_name, value)
|
78
|
+
else
|
79
|
+
allow_nil = !!rules[prop_name][:allow_nil]
|
80
|
+
type_check("`#{prop_name}`", value, klass, allow_nil)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def type_check(prop_name, value, klass, allow_nil)
|
85
|
+
return if allow_nil && value.nil?
|
86
|
+
return if value.is_a?(klass)
|
87
|
+
return if klass.respond_to?(:_react_param_conversion) &&
|
88
|
+
klass._react_param_conversion(value, :validate_only)
|
89
|
+
errors << "Provided prop #{prop_name} could not be converted to #{klass}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_allowed(prop_name, value)
|
93
|
+
return unless values = rules[prop_name][:values]
|
94
|
+
return if values.include?(value)
|
95
|
+
errors << "Value `#{value}` for prop `#{prop_name}` is not an allowed value"
|
96
|
+
end
|
97
|
+
|
98
|
+
def validate_required(props)
|
99
|
+
(rules.keys - props.keys).each do |name|
|
100
|
+
next unless rules[name][:required]
|
101
|
+
errors << "Required prop `#{name}` was not specified"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def validate_undefined(props)
|
106
|
+
(props.keys - rules.keys).each do |prop_name|
|
107
|
+
errors << "Provided prop `#{prop_name}` not specified in spec"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_value_array(name, value)
|
112
|
+
klass = rules[name][:type]
|
113
|
+
allow_nil = !!rules[name][:allow_nil]
|
114
|
+
value.each_with_index do |item, index|
|
115
|
+
type_check("`#{name}`[#{index}]", Native(item), klass[0], allow_nil)
|
116
|
+
end
|
117
|
+
rescue NoMethodError
|
118
|
+
errors << "Provided prop `#{name}` was not an Array"
|
119
|
+
end
|
120
|
+
|
121
|
+
def coerce_native_hash_values(hash)
|
122
|
+
hash.each do |key, value|
|
123
|
+
hash[key] = Native(value)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|