RedPotion allows a RubyMotion validation library to help you to validate data in a way that makes life easy.

There are two main aspects, so you can utilize RMQ validation to meet your needs:

  • Validation Utility - Simple validation methods
  • RMQ Validation Selection Rules - Dynamically apply validation rules to input
QUICK EXAMPLES:

# Examples of the Utility
rmq.validation.valid?('https://www.infinitered.com', :url) #true
rmq.validation.valid?(98.6, :number) #true

# Examples of Selection Rules
append(UITextField, :user).validates(:email)
append(UITextField, :password).validates(:strong_password)
append(UITextField, :pin).validates(:digits).validates(:length, exact_length: 5)

find(UITextField).valid? # checks if selected is valid
find(:password).clear_validations! #removes validations on selected

All validations are tied to RMQ Debugging mode. So you can turn them off in the application by entering debug mode. You can do so by starting your project with the flag set to true rake rmq_debug=true OR by setting the flag in the code/REPL with RubyMotionQuery::RMQ.debugging = true.

This allows you to quickly disable validation in your entire application during debugging.

RMQ Validation Utility

RMQ Comes with a simple utility to validate common forms of data input. Each validation type can support options specific to that validation rule.

The following validation types are baked in for the utility:

  • :email - Email address
  • :url - URL (including http(s))
  • :dateiso - ISO Date e.g. '2014-03-02'
  • :number - Any Real number e.g. 62.5
  • :digits - Any Natural numbers e.g. 65
  • :ipv4 - IPV4 addresses
  • :time - Military time
  • :uszip - US Zip code with optional extended 4
  • :ukzip - UK postal code
  • :usphone - US 7 OR 10 digit phone number with dots, dashes, or spaces for separators
  • :strong_password - Any string of at least 8 characters comprised of numbers, uppercase, and lowercase input
  • :has_upper - True if any uppercase letters
  • :has_lower - True if any lowercase letters
  • :presence - True with any non-whitespace input
  • :length - Allows you to validate length restrictions on input
  • :custom - Validates using whatever is passed in the regex parameter
Most of these are built from a collection of regular expressions that are fed into a regex_match? method. You can send a pull-request or use the custom rule to handle your own validations.

# examples
rmq.validation.valid?('test@test.com', :email) # returns true

rmq.validation.valid?('5045558989', :usphone) # returns true

rmq.validation.valid?('K1A 0B1', :uszip) # returns false

# Length takes a wide selection of input to facilitate your length validation needs
rmq.validation.valid?('test', :length, exact_length: 4) #true
rmq.validation.valid?('test', :length, min_length: 4) #true
rmq.validation.valid?('test', :length, max_length: 4) #true
# ranges
rmq.validation.valid?('test', :length, min_length: 2, max_length: 7) #true
rmq.validation.valid?('test', :length, exact_length: 2..7) #true
# strip whitespace
rmq.validation.valid?(' test ', :length, max_length: 5, strip: true) #true

# roll your own validation rule
rmq.validation.valid?('nacho', :custom, regex: Regexp.new('nachos?')) #true (could also do /nachos?/ notation

Universal Options

Some validation optinos are unique to that particular validation rule, but all validation rules have the following Universal Options:

allow_blank

By default all these tools are strict, but you can set the allows_blank option to true, which will cause a particular validation to return true IF it the input is blank. This can be useful in situations where data is optional.

e.g. Only validate weight is numeric if they entered a value for it.

white_list

In some situations you may have an outlying exception to the validation rule. Exceptions can be validated as true using the white_list parameter:

rmq.validation.valid?(some_url_input, :url, white_list: ['http://localhost:8080', 'http://localhost:3000'])
# => true for 'http://localhost:3000' even though it's not going to pass URL (missing TLD)

RMQ Validation Selection Rules

For a more robust use of RMQ and validation, there's an arsenal of RMQ integrated validation options and events. ANY utility rule can be used in a selection validation. Simply chain the validation you'd like applied to the UIViews you've selected with RMQ. For example:

# attach validation rules to UIViews
append(UITextField, :weight).validates(:digits)
append(UITextField, :name).validates(:presence)

# Later, you can check these fields to see if they have data that fits their associated validations
find(UITextField).valid?

Using the selection rules gets you a lot of validation help.

# Get a list of all views that were valid/invalid (updates on every .valid? call)
find(some_selection_criteria).invalid # returns all invalid views in the selected
find(some_selection_criteria).valid # returns all valid views in the selected

# you can remove validations just as easily
find(some_selection).clear_validations!

You can attach and fire events on the UIViews in a block.

append(UITextField).validates(:digits).
on(:valid) do |valid|
puts "This field is valid"
end.
on(:invalid) do |invalid|
puts "This field is invalid"
end

# The above will fire their events when validation gets called
find.all.valid?
# You can can call valid? during .on(:change) if you'd like your valid/invalid
# blocks to run instantaneously with given input.

Also, you can even get friendly error messages

# start off with a validated input
append(UITextField, :user).validates(:email)
find.all.valid? #run validation check

# Returns array of error messages for every invalid item in selection
find.all.validation_errors
# E.G ["Validation Error - input requires valid email."]

You can customize these error messages per validation rule by setting them in the stylesheet

# here in the stylesheet for this controller
def user(st)
st.validation_errors = {
email: "Please check your user email, and try again"
}
end

How do I add my own validations?

There are a few excellent ways to add your own validations. If you simply need to make exceptions for existing validations, consider looking into using white_list. If you need to use your own custom regex or validation code, then the following 2 methods are extremely useful.

custom rule

If your validation is specific to a single form, we suggest taking advantage of using the custom validation rule.

some_field = append(UITextField).validates(:custom, regex: /^test$/)
some_field.data("test")
some_field.valid?
# => true

add_validator

You can add your own validation with the add_validator method (Perhaps in your Application Stylesheet setup). Additionally, you're not limited to the bounds of a single regex. You can use the ruby methods you know and understand, as well as multiple parameters passed in opts.

rmq.validation.add_validator(:start_with) do |value, opts|
value.start_with?(opts[:prefix])
end

You can then use your new validator in your application:

some_field = append(UITextField).validates(:start_with, prefix: 'x')
some_field.data("test")
some_field.valid? # => false
some_field.data("xenophobia")
some_field.valid? # => true

If you find yourself needing a particular validation rule often, please patch back to RMQ's default rules with a Pull Request!