ruby_motion_query 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a97dab886591d15adcbca5f06dae750e7938c12
4
- data.tar.gz: 44496f23c8aba6bc4b0c9d1d686c932bfca5d9b7
3
+ metadata.gz: 6f9a3624a7543f1c6a828948bb3d2da590c8ad78
4
+ data.tar.gz: f377f2d6321fbe5a18b2e1fa4a8fedfff7023f63
5
5
  SHA512:
6
- metadata.gz: deb2ae07fb598b80d15827148d833d44ff1b2dbe16af222acb14194b8e1702bd69c7bcb5f4a1a59c8d13ae045898cfe0e2524bce8cdafa7c7ecbcf25a702e8e4
7
- data.tar.gz: 64bc7ca900954291b974dd027558c88b5cbf451b7f08be87b2121c9e427daa12d3ab5e85ba9c28f609fb6026bed0a2a8e0d6fd01191ceb7759612164b4fcb0e3
6
+ metadata.gz: 25be56991e401ba84649de80eccf69a45f7df4691507a7c1c5e8f1d2bb783bac5a8625608c0d757282bd8fe27bde29fe3afcf1d5b22eedba7b037f684c69a4a2
7
+ data.tar.gz: 9ccb416fa1ea67824729649c1b2e884682ec8b04feece7aec42f3dc2b705de0f2d3880a25d3a301ebc9dfd47fa6d86b20bc64df11c426ca975d6b5b313661fc7
@@ -73,6 +73,16 @@ module RubyMotionQuery
73
73
  end
74
74
  end
75
75
 
76
+ # Allow users to set data with equals
77
+ #
78
+ # @return [RMQ]
79
+ #
80
+ # @example
81
+ # rmq(my_view).data = 'some data'
82
+ def data=(new_data)
83
+ data(new_data)
84
+ end
85
+
76
86
  # @return [RMQ]
77
87
  def send(method, args = nil)
78
88
  selected.each do |view|
@@ -5,21 +5,33 @@ module RubyMotionQuery
5
5
  #
6
6
  # @return [RMQ]
7
7
  def animate(opts = {}, &block)
8
-
8
+
9
9
  animations_callback = (block || opts[:animations] || opts[:changes])
10
+ before_callback = opts[:before]
10
11
  after_callback = (opts[:completion] || opts[:after])
11
12
  return self unless animations_callback
12
13
 
13
-
14
14
  working_selected = self.selected
15
15
  self_rmq = self
16
16
 
17
17
  working_selected.each do |view|
18
18
  view_rmq = self_rmq.wrap(view)
19
19
 
20
+ return_var = nil
21
+
22
+ if before_callback
23
+ return_var = before_callback.call(view_rmq)
24
+ end
25
+
20
26
  animations_lambda = -> do
21
- # TODO, check arity and allow no params
22
- animations_callback.call(view_rmq)
27
+ case animations_callback.arity
28
+ when 0
29
+ animations_callback.call
30
+ when 1
31
+ animations_callback.call(view_rmq)
32
+ when 2
33
+ animations_callback.call(view_rmq, return_var)
34
+ end
23
35
  end
24
36
 
25
37
  after_lambda = if after_callback
@@ -146,7 +158,7 @@ module RubyMotionQuery
146
158
  opts = {
147
159
  duration: 0.5,
148
160
  animations: ->(cq) {
149
- cq.style do |st|
161
+ cq.style do |st|
150
162
  st.opacity = 1.0
151
163
  st.scale = 0.8
152
164
  end
@@ -168,14 +180,14 @@ module RubyMotionQuery
168
180
  duration: 0.4 + (rand(8) / 10),
169
181
  options: UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionBeginFromCurrentState,
170
182
  animations: ->(cq) {
171
- cq.style do |st|
183
+ cq.style do |st|
172
184
  st.top = @rmq.device.height + st.height
173
- st.rotation = 180 + rand(50)
185
+ st.rotation = 180 + rand(50)
174
186
  end
175
187
  },
176
188
  completion: ->(did_finish, q) {
177
189
  if did_finish
178
- q.style do |st|
190
+ q.style do |st|
179
191
  st.rotation = 0
180
192
  end
181
193
 
@@ -196,6 +208,74 @@ module RubyMotionQuery
196
208
  self.fade_out(duration: 0.2, after: lambda {|did_finish, rmq| rmq.animations.fade_in(duration: 0.2)})
197
209
  end
198
210
 
211
+ # @return [RMQ]
212
+ def slide_in(opts = {})
213
+ from_direction = opts[:from_direction] || :right
214
+
215
+ opts = {
216
+ duration: 0.5,
217
+ options: UIViewAnimationOptionCurveEaseIn,
218
+ before: ->(bq) {
219
+ start_frame = bq.get.frame
220
+
221
+ case from_direction
222
+ when :right
223
+ bq.move(l: rmq.device.width)
224
+ when :left
225
+ bq.move(l: -rmq.device.width)
226
+ when :top
227
+ bq.move(t: -rmq.device.height)
228
+ else :bottom
229
+ bq.move(t: rmq.device.height)
230
+ end
231
+ start_frame
232
+ },
233
+ animations: ->(aq, return_var) {
234
+ aq.frame = return_var
235
+ }
236
+ }.merge(opts)
237
+
238
+ @rmq.animate(opts)
239
+ end
240
+
241
+ # @return [RMQ]
242
+ def slide_out(opts = {})
243
+ remove_view = opts[:remove_view]
244
+ to_direction = opts[:to_direction] || :left
245
+
246
+ opts = {
247
+ duration: 0.5,
248
+ options: UIViewAnimationOptionCurveEaseIn,
249
+ before: ->(bq) {
250
+ start_frame = bq.get.frame
251
+ start_frame
252
+ },
253
+ animations: ->(aq, return_var) {
254
+ case to_direction
255
+ when :right
256
+ aq.move(l: rmq.device.screen_width)
257
+ when :left
258
+ aq.move(l: -rmq.device.screen_width)
259
+ when :top
260
+ aq.move(t: -rmq.device.screen_height)
261
+ else :bottom
262
+ aq.move(t: rmq.device.screen_height)
263
+ end
264
+ },
265
+ completion: ->(did_finish, q) {
266
+ if did_finish
267
+ if remove_view
268
+ q.remove
269
+ else
270
+ q.hide
271
+ end
272
+ end
273
+ }
274
+ }.merge(opts)
275
+
276
+ @rmq.animate(opts)
277
+ end
278
+
199
279
  # @return [RMQ]
200
280
  def start_spinner(style = UIActivityIndicatorViewStyleGray)
201
281
  spinner = Animations.window_spinner(style)
@@ -210,7 +290,7 @@ module RubyMotionQuery
210
290
  @rmq.create_rmq_in_context(spinner)
211
291
  end
212
292
 
213
- protected
293
+ protected
214
294
 
215
295
  def self.window_spinner(style = UIActivityIndicatorViewStyleGray)
216
296
  @_window_spinner ||= begin
@@ -12,7 +12,12 @@ module RubyMotionQuery
12
12
  tags.keys
13
13
  end
14
14
 
15
- # *Do not* use this, use {RMQ#tag} instead:
15
+ def validation_errors; @_validation_errors ||= {}; end
16
+ def validation_errors=(value); @_validation_errors = value; end
17
+ def validations; @_validations ||= []; end
18
+ def validations=(value); @_validations = value; end
19
+
20
+ # *Do not* use this, use {RMQ#tag} instead:
16
21
  # @example
17
22
  # rmq(my_view).tag(:foo)
18
23
  def tag(*tag_or_tags)
@@ -25,7 +30,7 @@ module RubyMotionQuery
25
30
  end
26
31
  elsif tag_or_tags.is_a?(Hash)
27
32
  tag_or_tags.each do |tag_name, tag_value|
28
- tags[tag_name] = tag_value
33
+ tags[tag_name] = tag_value
29
34
  end
30
35
  elsif tag_or_tags.is_a?(Symbol)
31
36
  tags[tag_or_tags] = 1
@@ -13,7 +13,7 @@ module RubyMotionQuery
13
13
  end
14
14
 
15
15
  # @return [Debug]
16
- def debug
16
+ def debug
17
17
  Debug
18
18
  end
19
19
  end
@@ -48,7 +48,7 @@ module RubyMotionQuery
48
48
  Deep log - #{label}
49
49
  At: #{Time.now.to_s}
50
50
 
51
- Callers:
51
+ Callers:
52
52
  #{callers.join("\n - ")}
53
53
 
54
54
  Objects:
@@ -61,7 +61,7 @@ module RubyMotionQuery
61
61
  label
62
62
  end
63
63
 
64
- # Warning, this is very slow to output log, checking truthy however is
64
+ # Warning, this is very slow to output log, checking truthy however is
65
65
  # basically as performant as an if statement
66
66
  #
67
67
  # @example
@@ -3,7 +3,9 @@ module RubyMotionQuery
3
3
  attr_accessor :block, :recognizer, :event, :sdk_event_or_recognizer, :gesture, :sender
4
4
 
5
5
  def initialize(sender, event, block)
6
- if @sdk_event_or_recognizer = VIEW_GESTURES[event]
6
+ if CONTROL_EVENTS[event] == ValidationEvent
7
+ return ValidationEvent.new(block)
8
+ elsif @sdk_event_or_recognizer = VIEW_GESTURES[event]
7
9
  @gesture = true
8
10
  elsif sender.is_a?(UIControl)
9
11
  @gesture = false
@@ -127,7 +129,9 @@ module RubyMotionQuery
127
129
 
128
130
  application: UIControlEventApplicationReserved,
129
131
  system: UIControlEventSystemReserved,
130
- all: UIControlEventAllEvents
132
+ all: UIControlEventAllEvents,
133
+ valid: ValidationEvent,
134
+ invalid: ValidationEvent
131
135
  }
132
136
 
133
137
  VIEW_GESTURES = {
@@ -39,6 +39,9 @@ module RubyMotionQuery
39
39
  # :application
40
40
  # :system
41
41
  # :all
42
+ #
43
+ # :valid
44
+ # :invalid
42
45
 
43
46
  # Gestures for UIView
44
47
  # :tap
@@ -53,17 +56,17 @@ module RubyMotionQuery
53
56
  # :long_press
54
57
 
55
58
  # Options for gestures
56
- # :cancels_touches_in_view
57
- # :delegate
58
- # :taps_required
59
- # :fingers_required
60
- # :maximum_number_of_touches
61
- # :minimum_number_of_touches
62
- # :allowable_movement
63
- # :minimum_press_duration
64
- # :direction
65
- # :rotation
66
- # :scale
59
+ # :cancels_touches_in_view
60
+ # :delegate
61
+ # :taps_required
62
+ # :fingers_required
63
+ # :maximum_number_of_touches
64
+ # :minimum_number_of_touches
65
+ # :allowable_movement
66
+ # :minimum_press_duration
67
+ # :direction
68
+ # :rotation
69
+ # :scale
67
70
  #
68
71
  # @example
69
72
  # rmq.append(UIButton).on(:touch) do |sender|
@@ -86,7 +89,7 @@ module RubyMotionQuery
86
89
  # end
87
90
  def on(event, args = {}, &block)
88
91
  selected.each do |view|
89
- events(view).on(view, event, args, &block)
92
+ events(view).on(view, event, args, &block)
90
93
  end
91
94
 
92
95
  self
@@ -130,8 +133,8 @@ module RubyMotionQuery
130
133
  def on(view, event, args = {}, &block)
131
134
  raise "[RMQ Error] Event already exists on this object: #{event}. Remove first, using .off" if @event_set[event]
132
135
 
133
- if rmqe = RubyMotionQuery::Event.new(view, event, block)
134
- rmqe.set_options(args)
136
+ if rmqe = event_instance(view, event, block)
137
+ rmqe.set_options(args) if rmqe.respond_to? :set_options
135
138
 
136
139
  @event_set[event] = rmqe
137
140
  end
@@ -143,14 +146,23 @@ module RubyMotionQuery
143
146
  events.flatten!
144
147
  events = @event_set.keys if events.length == 0
145
148
 
146
- events.each do |event|
149
+ events.each do |event|
147
150
  if rm_event = @event_set.delete(event)
148
- rm_event.remove
151
+ rm_event.remove
149
152
  end
150
153
  end
151
154
 
152
155
  self
153
156
  end
154
157
 
158
+ private
159
+
160
+ def event_instance(view, event, block)
161
+ if [:valid, :invalid].include? event
162
+ RubyMotionQuery::ValidationEvent.new(view, event, block)
163
+ else
164
+ RubyMotionQuery::Event.new(view, event, block)
165
+ end
166
+ end
155
167
  end
156
168
  end
@@ -104,13 +104,13 @@ module RubyMotionQuery
104
104
  NAV_BAR_BOTTOM = 64
105
105
 
106
106
  DEFAULT = {
107
- num_columns: 10,
107
+ num_columns: 12,
108
108
  column_gutter: 10,
109
- num_rows: 16,
109
+ num_rows: 18,
110
110
  row_gutter: 10,
111
111
  content_left_margin: 10,
112
112
  content_right_margin: 10,
113
- content_top_margin: 70,
113
+ content_top_margin: 74,
114
114
  content_bottom_margin: 10
115
115
  }
116
116
 
@@ -381,6 +381,12 @@ module RubyMotionQuery
381
381
  def accessibility_label=(value)
382
382
  @view.accessibilityLabel = value
383
383
  end
384
+
385
+ def validation_errors=(values)
386
+ # set custom validation messages on rules
387
+ @view.rmq_data.validation_errors = values
388
+ end
389
+
384
390
  end
385
391
  end
386
392
  end
@@ -50,7 +50,7 @@ module RubyMotionQuery
50
50
  end
51
51
 
52
52
  if created
53
- new_view.rmq_did_create(self.wrap(new_view))
53
+ new_view.rmq_did_create(self.wrap(new_view))
54
54
  new_view.rmq_created
55
55
  end
56
56
  new_view.rmq_build
@@ -65,16 +65,16 @@ module RubyMotionQuery
65
65
  end
66
66
  alias :insert :add_subview
67
67
 
68
- # Performs a create, then appends view to the end of the subview array of the
68
+ # Performs a create, then appends view to the end of the subview array of the
69
69
  # views you have selected (or the rootview if you have nothing selected).
70
70
  #
71
71
  # When you build, create, or append a view, the method rmq_build is called
72
72
  # inside the view. If you are creating a your own subclass of a UIView, then
73
- # that is a good place to do your initialization. Your view is created, then
73
+ # that is a good place to do your initialization. Your view is created, then
74
74
  # appended, then rmq_build is called, then the style is applied (if it exists)
75
75
  #
76
- # @example
77
- # # Creating a new view instance then append it. Passing in the class
76
+ # @example
77
+ # # Creating a new view instance then append it. Passing in the class
78
78
  # # to create
79
79
  # rmq.append(UIButton, :my_button_style)
80
80
  # @title = rmq.append(ULabel, :title).get
@@ -82,7 +82,7 @@ module RubyMotionQuery
82
82
  # # You can also pass in an existing view
83
83
  # my_view = UIView.alloc.initWithFrame([[0,0],[10,10]])
84
84
  # rmq.append(my_view, :my_style)
85
- #
85
+ #
86
86
  # # Stylename is optional
87
87
  # rmq.append(UIImageView)
88
88
  #
@@ -121,21 +121,21 @@ module RubyMotionQuery
121
121
  end
122
122
  alias :prepend! :unshift!
123
123
 
124
- # Creates a view then returns an rmq with that view in it. It does not add that
124
+ # Creates a view then returns an rmq with that view in it. It does not add that
125
125
  # view to the view tree (append does this). This is useful for stuff like creating
126
- # table cells. You can use the rmq_did_create method, just like you do when you
126
+ # table cells. You can use the rmq_did_create method, just like you do when you
127
127
  # append a subview
128
128
  #
129
129
  # @return [RMQ] wrapping the view that was just create
130
130
  #
131
131
  # @example
132
132
  # def tableView(table_view, cellForRowAtIndexPath: index_path)
133
- # cell = tableView.dequeueReusableCellWithIdentifier(CELL_IDENTIFIER) || begin
133
+ # cell = tableView.dequeueReusableCellWithIdentifier(CELL_IDENTIFIER) || begin
134
134
  # rmq.create(StoreCell, :store_cell, reuse_identifier: CELL_IDENTIFIER)
135
135
  # end
136
136
  # end
137
137
  #
138
- # class StoreCell < UITableViewCell
138
+ # class StoreCell < UITableViewCell
139
139
  # def rmq_did_create(self_in_rmq)
140
140
  # self_in_rmq.append(UILabel, :title_label)
141
141
  # end
@@ -160,7 +160,7 @@ module RubyMotionQuery
160
160
  # in collectionview cells for example
161
161
  #
162
162
  # @example
163
- # # In your collectionview
163
+ # # In your collectionview
164
164
  # rmq.build(cell) unless cell.reused
165
165
  #
166
166
  # # Then in your cell
@@ -174,6 +174,15 @@ module RubyMotionQuery
174
174
  add_subview view, opts
175
175
  end
176
176
 
177
+ # Same as build, but instantly returns the view, without having to use .get
178
+ #
179
+ # @example
180
+ # @my_cell = rmq.build! cell
181
+ def build!(view, style = nil, opts = {})
182
+ build(view, style, opts).get
183
+ end
184
+
185
+
177
186
  protected
178
187
 
179
188
  def create_view(klass, opts)
@@ -1,5 +1,6 @@
1
1
  module RubyMotionQuery
2
2
  class RMQ
3
+
3
4
  # @return [Validation]
4
5
  def self.validation
5
6
  Validation
@@ -9,9 +10,105 @@ module RubyMotionQuery
9
10
  def validation
10
11
  Validation
11
12
  end
12
- end
13
+
14
+ # @return [RMQ]
15
+ def validates(rule, options={})
16
+ selected.each do |view|
17
+ view.rmq_data.validations << Validation.new(rule, options)
18
+ end
19
+ self
20
+ end
21
+
22
+ # @return [RMQ]
23
+ def clear_validations!
24
+ selected.each do |view|
25
+ view.rmq_data.validations = []
26
+ end
27
+ self
28
+ end
29
+
30
+ # This method validates all the selected and is responsible
31
+ # for calling invalid/valid events
32
+ #
33
+ # @return [Boolean] false if any validations fail
34
+ def valid?
35
+ result = true
36
+
37
+ selected.each do |view|
38
+ view.rmq_data.validations.each do |validation|
39
+
40
+ has_events = view.rmq_data.events
41
+
42
+ if validation.valid?(rmq(view).data)
43
+ if has_events && view.rmq_data.events.has_event?(:valid)
44
+ view.rmq_data.events[:valid].fire!
45
+ end
46
+ else
47
+ if has_events && view.rmq_data.events.has_event?(:invalid)
48
+ view.rmq_data.events[:invalid].fire!
49
+ end
50
+ result = false
51
+ end
52
+ end
53
+ end
54
+ return result
55
+ end
56
+
57
+ # @return [Array] of error messages for failed validations
58
+ def validation_errors
59
+ errors = []
60
+ selected.each do |view|
61
+ view.rmq_data.validations.each do |validation|
62
+ unless validation.valid_status
63
+ default_error = "Validation Error - input requires valid #{validation.rule_name.to_s}."
64
+ rule_message = view.rmq_data.validation_errors[validation.rule_name] || default_error
65
+ errors.push(rule_message)
66
+ end
67
+ end
68
+ end
69
+ return errors
70
+ end
71
+
72
+ # @return [Array] of views where validations have failed
73
+ def invalid
74
+ invalid = []
75
+ selected.each do |view|
76
+ view.rmq_data.validations.each do |validation|
77
+ invalid.push(view) unless validation.valid_status
78
+ end
79
+ end
80
+ return invalid
81
+ end
82
+
83
+ # @return [Array] of views where validations have failed
84
+ def valid
85
+ invalid = []
86
+ selected.each do |view|
87
+ view.rmq_data.validations.each do |validation|
88
+ invalid.push(view) if validation.valid_status
89
+ end
90
+ end
91
+ return invalid
92
+ end
93
+
94
+ end # End RMQ
13
95
 
14
96
  class Validation
97
+ attr_reader :valid_status, :rule_name
98
+
99
+ def initialize(rule, options={})
100
+ @rule = @@validation_methods[rule]
101
+ raise "RMQ validation error: :#{rule} is not one of the supported validation methods." unless @rule
102
+ @rule_name = rule
103
+ @options = options
104
+ @valid_status = true
105
+ end
106
+
107
+ def valid?(data, options={})
108
+ @options = options.merge(@options)
109
+ @valid_status = @rule.call(data, @options)
110
+ end
111
+
15
112
  class << self
16
113
  # Validation Regex from jQuery validation -> https://github.com/jzaefferer/jquery-validation/blob/master/src/core.js#L1094-L1200
17
114
  EMAIL = Regexp.new('^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
@@ -26,18 +123,52 @@ module RubyMotionQuery
26
123
  USZIP = Regexp.new('^\d{5}(-\d{4})?$')
27
124
  # 7 or 10 digit number, delimiters are spaces, dashes, or periods
28
125
  USPHONE = Regexp.new('^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]‌​)\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-‌​9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})$')
29
-
126
+ # Strong password (at least [8 chars, 1 upper, 1 lower, 1 number])
127
+ STRONGPW = Regexp.new('^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{8,}$')
128
+ # Has at least 1 uppercase letter
129
+ HASUPPER = Regexp.new('^(?=.*[A-Z]).+$')
130
+ # Has at least 1 lowercase letter
131
+ HASLOWER = Regexp.new('^(?=.*[a-z]).+$')
132
+ # Has some kind of value not just whitespace (doesn't require data to be stripped)
133
+ PRESENCE = Regexp.new('\S+')
30
134
 
31
135
  @@validation_methods = {
32
- :email => lambda { |value| Validation.regex_match?(value, EMAIL)},
33
- :url => lambda { |value| Validation.regex_match?(value, URL)},
34
- :dateiso => lambda { |value| Validation.regex_match?(value, DATEISO)},
35
- :number => lambda { |value| Validation.regex_match?(value, NUMBER)},
36
- :digits => lambda { |value| Validation.regex_match?(value, DIGITS)},
37
- :ipv4 => lambda { |value| Validation.regex_match?(value, IPV4)},
38
- :time => lambda { |value| Validation.regex_match?(value, TIME)},
39
- :uszip => lambda { |value| Validation.regex_match?(value, USZIP)},
40
- :usphone => lambda { |value| Validation.regex_match?(value, USPHONE)}
136
+ :email => lambda { |value, opts| Validation.regex_match?(value, EMAIL)},
137
+ :url => lambda { |value, opts| Validation.regex_match?(value, URL)},
138
+ :dateiso => lambda { |value, opts| Validation.regex_match?(value, DATEISO)},
139
+ :number => lambda { |value, opts| Validation.regex_match?(value, NUMBER)},
140
+ :digits => lambda { |value, opts| Validation.regex_match?(value, DIGITS)},
141
+ :ipv4 => lambda { |value, opts| Validation.regex_match?(value, IPV4)},
142
+ :time => lambda { |value, opts| Validation.regex_match?(value, TIME)},
143
+ :uszip => lambda { |value, opts| Validation.regex_match?(value, USZIP)},
144
+ :usphone => lambda { |value, opts| Validation.regex_match?(value, USPHONE)},
145
+ :strong_password => lambda { |value, opts| Validation.regex_match?(value, STRONGPW)},
146
+ :has_upper => lambda { |value, opts| Validation.regex_match?(value, HASUPPER)},
147
+ :has_lower => lambda { |value, opts| Validation.regex_match?(value, HASLOWER)},
148
+ :presence => lambda { |value, opts| Validation.regex_match?(value, PRESENCE)},
149
+ :length => lambda { |value, opts|
150
+ opts = {
151
+ exact_length: nil,
152
+ max_length: Float::INFINITY,
153
+ min_length: 0,
154
+ strip: false
155
+ }.merge(opts)
156
+
157
+ # Range magic 8..16
158
+ if opts[:exact_length].is_a? Range
159
+ opts[:min_length] = opts[:exact_length].begin
160
+ opts[:max_length] = opts[:exact_length].end
161
+ opts[:exact_length] = nil
162
+ end
163
+
164
+ # allowing option to strip input before assessing length
165
+ value.strip! if opts[:strip]
166
+
167
+ # check length validation
168
+ v = if opts[:exact_length] then (value.length == opts[:exact_length]) else true end
169
+ v = v && value.length <= opts[:max_length]
170
+ v = v && value.length >= opts[:min_length]
171
+ }
41
172
  }
42
173
 
43
174
  # Add tags
@@ -46,23 +177,21 @@ module RubyMotionQuery
46
177
  # rmq.validation.valid?(53.8, :number)
47
178
  # rmq.validation.valid?(54, :digits)
48
179
  # rmq.validation.valid?('https://www.tacoland.com', :url)
49
- # rmq.validation.valid?('2014-03-02'), :dateiso)
180
+ # rmq.validation.valid?('2014-03-02', :dateiso)
181
+ # rmq.validation.valid?('', :email, allow_blank: true)
50
182
  #
51
183
  # @return [Boolean]
52
- def valid?(value, *rule_or_rules)
53
- #shortcircuit if debugging
184
+ def valid?(value, rule, options={})
185
+ # shortcircuit if debugging
54
186
  return true if RubyMotionQuery::RMQ.debugging?
55
- rule_or_rules.each do |rule|
56
- # only supported validations
57
- raise "RMQ validation error: :#{rule} is not one of the supported validation methods." unless @@validation_methods.include?(rule)
58
- #return false if validation_failed
59
- return false unless @@validation_methods[rule].call(value)
60
- end
61
- true
187
+ # shortcircuit for optionals
188
+ return true if (options[:allow_blank] && (value.nil? || value.empty?))
189
+
190
+ Validation.new(rule).valid?(value, options)
62
191
  end
63
192
 
64
193
  def regex_match?(value, regex)
65
- (value.to_s =~ regex) == 0
194
+ (value.to_s =~ regex) != nil
66
195
  end
67
196
 
68
197
  end
@@ -0,0 +1,24 @@
1
+ module RubyMotionQuery
2
+ class ValidationEvent
3
+ def initialize(sender, event, block)
4
+ @sender = sender
5
+ @event = event
6
+ @block = block
7
+ end
8
+
9
+ def fire!
10
+
11
+ if @block
12
+ case @block.arity
13
+ when 2
14
+ @block.call(@sender, self)
15
+ when 1
16
+ @block.call(@sender)
17
+ else
18
+ @block.call
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module RubyMotionQuery
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
 
4
4
  class RMQ
5
5
  def version
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_motion_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Werth
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-02 00:00:00.000000000 Z
12
+ date: 2014-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bacon
@@ -100,6 +100,7 @@ files:
100
100
  - motion/ruby_motion_query/traverse.rb
101
101
  - motion/ruby_motion_query/utils.rb
102
102
  - motion/ruby_motion_query/validation.rb
103
+ - motion/ruby_motion_query/validation_event.rb
103
104
  - motion/ruby_motion_query/version.rb
104
105
  - templates/collection_view_controller/app/controllers/name_controller.rb
105
106
  - templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb