Now that you got the basic structure of Rules down,
let's talk specifically about validation rules.
Validation rules are primarily used for enforcing the structure of your data and
the format of your content.
Take a look over here.
This is the start of a validation rule for
a new value being written in the listName field.
And in plain English what it's saying,
is that the value that's written here must be a string.
And it's placement where it's nested inside userLists and
then these two wildcard variables, and the property name listName
makes it specifically a rule that affects the listName values.
So let's take an actual look at the variables and
methods that are used within this expression itself.
First I'd like to point out this variable called newData.
When you're writing your validation rules, you're almost always going to
need a way to refer to the value that is either currently there, or
that their users try to write to that location.
Because of this, the Firebase rules language provides two
predefined variables specifically for these values.
And they are data and newData.
You can use these anywhere within your rules.
Now data refers to the data as it currently is, and
newData refers to the data after a write has taken place.
In the rules language, these have the variable types of RuleDataSnapshots.
And they're called DataSnapshots, because they can either be a single
value or a whole portion of data in the Firebase database.
So just to be explicit, if I had a shopping list
with something like Lyla's List, and then I went to edit it.
Lyla's List would be the current value, which would be stored in data.
Awesome List.
Lyla's Awesome List, would be the value that'd be stored in newData.
Now as I stated, both data and newData are what's known as RuledDataSnapshots.
And RuledDataSnapshots have a bunch of methods that you can use in the rules.
I'll go ahead and link to the API docs,
where you can read to your heart's content about all of these methods.
But here are a couple of interest.
Because these are DataSnapshots, which know their location in the tree.
You can use the parent or child method to navigate to other nodes in the tree.
This let's you do cool things like create rules that compare one of the database
to another part of the database.
For example, if you wanted to access the owner value from your listName rule,
you could write newData.parent,
which would take you from listName up to the parent here.
Then .child('owner'), which would take you down to the owner.
Then finally val,
which is a method that let's you get the current value at that variable.
And for the user lylafish at this specific node,
this rule would return this value here.
And then you could use it in something like a comparison.
In this case this is a kind of silly validate rule that doesn't
make much sense.
It's saying that the newData that you're writing for
the listName must be the same as the owner's email.
So you'd have a bunch of listNames named after owners.
But hopefully that gives a little bit more insight about how you might
be able to use the parent or child methods.
Note that the ability to use parent in the rules is somewhat different than
the DataSnapshots that we've been using in our Android app.
When you get a DataSnapshot on the client side, you
can't see anything that is the parent of the location that you requested.
In the rules though,
you can look at any other part of the database in order to make a rule.
Which is why you can use a method like parent.
Now as I mentioned, you can use the value method,
and that'll give you a primitive value back from a data or newData object.
In addition, you have methods that check for the type at a current location.
And exist is actually a really helpful method to use when you're writing rules
that are specific to whether a value is being added or removed.
And with that, we can see that this isString method here, is one of the type
method which is making sure that the value stored in newData is a string.
Let's see an example of a little bit of a more complicated rule here.
So here we've added another little bit to this rule.
And basically what this says, is that newData is both a string, and
that this new listName has at least one character in it.
From this example, you can see that JavaScript Logical and
Comparison Operators are available to you.
In addition, when you're dealing with values that are strings,
there's a subset of Javascript string methods and
properties which are available to you.
newData.val().length is one such example,
the length value is available to you.
And another helpful one is the matches method,
which allows you to match a string against a regular expression.
For example, if you wanted to validate data at a location to see if it's in
the form of an email address, you could use standard email address Regex.
And then use matches to do the actual comparison.
So that's pretty much the summary of writing a single validation rule.
In addition,
there are a few other things that you might want to keep in mind.
The first is that whenever you write server side validation rules, you should
also be writing the corresponding client side validation rules.
For example,
in the dialog where somebody changes a shopping lists listName, you should
go ahead and check that that listName's actually greater than zero characters.
There's no sense wasting one are your users' data plans,
by pinging the database with improperly formatted data.
So go ahead and save them and yourself that useless network traffic.
Second, remember that validation rules are only checked
when you're actually writing data.
This maybe pretty straightforward, but they're not checked when you read data.
And finally, validation rules are not checked when you're deleting data,
otherwise you'd basically never be able to remove anything from the database.
For example, if I try to set a listName here to null, and
it was checking validation rules, then it would complain that null is neither
a string nor has a length greater than zero.
But it doesn't do those checks, and
instead you don't have any validation checks when you're deleting something.
Okay, so now that you know how to write a single rule,
let's talk about validating an entire structure.