diff --git a/docs/client/basic/sections/collections.md b/docs/client/basic/sections/collections.md index 1861561ea7..f3b19e4461 100644 --- a/docs/client/basic/sections/collections.md +++ b/docs/client/basic/sections/collections.md @@ -3,35 +3,37 @@

Collections

Meteor stores data in *collections*. JavaScript objects stored in collections -are called `documents`. To get started, declare a collection with `new -Mongo.Collection`. +are called `documents`. To get started, declare a collection with +`new Mongo.Collection`. {{> autoApiBox "Mongo.Collection"}} -Calling this constructor creates a collection object which acts just like a -MongoDB collection. If you pass a name when you create the collection, then you -are declaring a persistent collection — one that is stored on the server and -seen by all users. +Calling the `Mongo.Collection` constructor creates a collection object +which acts just like a MongoDB collection. If you pass a name when you +create the collection, then you are declaring a persistent collection +— one that is stored on the server and seen by all users. -Since client code and server code can both access the same collection using the -same API, it's usually best to declare persistent collections as global -variables in a JavaScript file that's present on the client and the server. +To allow both client code and server code to access the same collection +using the same API, it's usually best to declare collections as global +variables in a JavaScript file that's present on both client and server. -Here's an example of declaring a collection: +Here's an example of declaring two named, persistent collections as global +variables: ``` -// In a JS file that's loaded on the client and server +// In a JS file that's loaded on the client and the server Posts = new Mongo.Collection("posts"); Comments = new Mongo.Collection("comments"); ``` -If you pass null as the name, then you're creating a local collection. It's not -synchronized anywhere; it's just a local collection of JavaScript objects that -supports Mongo-style find, insert, update, and remove operations. +If you pass `null` as the name, then you're creating a local +collection. Local collections are not synchronized between the client and +the server; they are just temporary collections of JavaScript objects that +support Mongo-style `find`, `insert`, `update`, and `remove` operations. -By default, Meteor automatically publishes every document in your collection to -each connected client. To turn this behavior off, remove the autopublish -package: +By default, Meteor automatically publishes every document in your +collection to each connected client. To disable this behavior, you must +remove the `autopublish` package: ``` $ meteor remove autopublish @@ -45,24 +47,28 @@ Use `findOne` or `find` to retrieve documents from a collection. {{> autoApiBox "Mongo.Collection#findOne"}} -This method lets you retrieve a specific document from your collection. It is -simplest to call it with a document id: +This method lets you retrieve a specific document from your +collection. The `findOne` method is most commonly called with a specific +document `_id`: ``` var post = Posts.findOne(postId); ``` -You can also call `findOne` with a Mongo selector, which is an object that -specifies a set of rules for the document you're looking for: +However, you can also call `findOne` with a Mongo selector, which is an +object that specifies a required set of attributes of the desired +document. For example, this selector ``` -// this selector var post = Posts.findOne({ createdBy: "12345", title: {$regex: /first/} }); +``` -// will match this document +will match this document + +``` { createdBy: "12345", title: "My first post!", @@ -72,17 +78,20 @@ var post = Posts.findOne({ You can read about MongoDB query operators such as `$regex`, `$lt` (less than), `$text` (text search), and more in the [MongoDB -documentation](http://docs.mongodb.org/manual/reference/operator/query/). One -interesting thing to note is that Mongo selectors also match items in arrays. -For example: +documentation](http://docs.mongodb.org/manual/reference/operator/query/). + +One useful behavior that might not be obvious is that Mongo selectors also +match items in arrays. For example, this selector ``` -// this selector Post.findOne({ tags: "meteor" }); +``` -// will match this document +will match this document + +``` { title: "I love Meteor", createdBy: "242135223", @@ -91,18 +100,22 @@ Post.findOne({ ``` The `findOne` method is reactive just like [`Session.get`](#session_get), -meaning if you use it inside a [template helper](#template_helpers) or a -[`Tracker.autorun`](#tracker_autorun), it will automatically rerender -the view or rerun the computation if the returned document changes. This also -means that sometimes `findOne` will return `null` if the document is removed -from the collection, so you should be prepared to accept that value. +meaning that, if you use it inside a [template helper](#template_helpers) +or a [`Tracker.autorun`](#tracker_autorun) callback, it will automatically +rerender the view or rerun the computation if the returned document +changes. + +Note that `findOne` will return `null` if it fails to find a matching +document, which often happens after the document has been removed from the +collection, so you should be prepared to handle `null` values. {{> autoApiBox "Mongo.Collection#find"}} -The `find` method is similar to `findOne`, but instead of returning a single -document it returns a MongoDB cursor. A cursor is a special object that refers -to the documents that might be returned from a query. You can pass a cursor into -a template helper anywhere you could pass an array: +The `find` method is similar to `findOne`, but instead of returning a +single document it returns a MongoDB *cursor*. A cursor is a special +object that represents a list of documents that might be returned from a +query. You can pass a cursor into a template helper anywhere you could +pass an array: ``` Template.blog.helpers({ @@ -124,8 +137,8 @@ Template.blog.helpers({ ``` -If you want to actually retrieve all of the documents from a cursor, call -`.fetch()` like this: +When you want to retrieve the current list of documents from a cursor, +call the cursor's `.fetch()` method: ``` // get an array of posts @@ -154,8 +167,8 @@ Posts.insert({ Every document in every `Mongo.Collection` has an `_id` field. It must be unique, and is automatically generated if you don't provide one. The `_id` -field should be used to refer to a specific document, and can be used to -retrieve that document using [`collection.findOne`](#findOne). +field can be used to retrieve a specific document using +[`collection.findOne`](#findOne). {{> autoApiBox "Mongo.Collection#update"}} @@ -165,13 +178,14 @@ changes should be made to the matched documents. Watch out - unless you use an operator like `$set`, `update` will simply replace the entire matched document with the modifier. +Here's an example of setting the `content` field on all posts whose titles +contain the word "first": + ``` -// Sets the content field on all posts -// that have 'first' in the title Posts.update({ title: {$regex: /first/} }, { - $set: { content: "Tomorrow will be a great day." } + $set: {content: "Tomorrow will be a great day."} }); ``` @@ -179,40 +193,40 @@ You can read about all of the different operators that are supported in the [MongoDB documentation](http://docs.mongodb.org/manual/reference/operator/update/). There's one catch: when you call `update` on the client, you can only find -documents by theid `_id` field. To use all of the possible selectors, you must -call `update` in server code or from a [method](#meteor_methods). +documents by their `_id` field. To use all of the possible selectors, you +must call `update` in server code or from a [method](#meteor_methods). {{> autoApiBox "Mongo.Collection#remove"}} -This method uses the same selectors as `find` and `update`, and removes any -documents that match the selector from the database. Use `remove` carefully - -there's no way to get that data back. - -Just like with `update`, you can only remove documents by using their `_id` -field unless `remove` is called in server code or from a -[method](#meteor_methods). +This method uses the same selectors as `find` and `update`, and removes +any documents that match the selector from the database. Use `remove` +carefully — there's no way to get that data back. +As with `update`, client code can only remove documents by `_id`, whereas +server code and [methods](#meteor_methods) can remove documents using any +selector. {{> autoApiBox "Mongo.Collection#allow"}} In newly created apps, Meteor allows almost any calls to `insert`, `update`, and `remove` from any client or server code. This is because apps started with -`meteor create` include the `insecure` package by default to speed up +`meteor create` include the `insecure` package by default to simplify development. Obviously, if any user could change the database whenever they -wanted it would be bad for security, so we should remove `insecure` and specify -some permissions rules. +wanted it would be bad for security, so it is important to remove the +`insecure` package and specify some permissions rules: ``` $ meteor remove insecure ``` -Once we have removed this package, we can use the `allow` and `deny` methods to -control who can perform which operations on the database. By default, all -operations on the client are denied, so we need to add some `allow` rules. -Keep in mind that server code and code inside [methods](#meteor_methods) is -not affected by `allow` and `deny` - these rules only apply when `insert`, -`update`, and `remove` are called from untrusted client code. +Once you have removed the `insecure` package, use the `allow` and `deny` +methods to control who can perform which operations on the database. By +default, all operations on the client are denied, so we need to add some +`allow` rules. Keep in mind that server code and code inside +[methods](#meteor_methods) are not affected by `allow` and `deny` — +these rules only apply when `insert`, `update`, and `remove` are called +from untrusted client code. For example, we might say that users can only create new posts if the `createdBy` field matches the ID of the current user, so that users can't @@ -234,8 +248,9 @@ Posts.allow({ }); ``` -There are three possible callbacks, that get different arguments. The first -argument is always the `_id` of the logged in user. +The `allow` method accepts three possible callbacks: `insert`, `remove`, +and `update`. The first argument to all three callbacks is the `_id` of +the logged in user, and the remaining arguments are as follows: 1. `insert(userId, document)` @@ -259,9 +274,10 @@ argument is always the `_id` of the logged in user. {{> autoApiBox "Mongo.Collection#deny"}} -Deny lets you override parts of your `allow` rules. While only one of your -`allow` callbacks has to return true to allow a modification, _every one_ of -your `deny` callbacks has to return false for the database change to happen. +The `deny` method lets you selectively override your `allow` rules. While +only one of your `allow` callbacks has to return true to allow a +modification, _every one_ of your `deny` callbacks has to return false for +the database change to happen. For example, if we wanted to override part of our `allow` rule above to exclude certain post titles: @@ -276,4 +292,4 @@ Posts.deny({ }); ``` -{{/template}} \ No newline at end of file +{{/template}} diff --git a/docs/client/basic/sections/methods.md b/docs/client/basic/sections/methods.md index f2cd2cfd55..e6f9e3d701 100644 --- a/docs/client/basic/sections/methods.md +++ b/docs/client/basic/sections/methods.md @@ -10,9 +10,9 @@ Methods can return values and throw errors. {{> autoApiBox "Meteor.methods"}} -Calling `methods` on the server defines functions that can be called remotely by -clients. Here's an example of a method that checks its arguments and throws an -error: +Calling `Meteor.methods` on the server defines functions that can be +called remotely by clients. Here's an example of a method that checks its +arguments and throws an error: ``` // On the server @@ -38,18 +38,12 @@ Meteor.methods({ }); ``` +The [`check`](#check) function is a convenient way to enforce the expected +[types and structure](#matchpatterns) of method arguments. + Inside your method definition, `this` is bound to a method invocation object, -which has a few useful properties: - -* `userId`: the id of the current user. -* `unblock`: when called, allows the next method from this client to -begin running. Useful if this method is doing something that takes a long time, -like making an API call. -* `isSimulation`: true if this code is inside a method stub. - -Since methods usually expect particular types as arguments, -use [`check`](#check) to ensure your method arguments have -the correct [types and structure](#matchpatterns). +which has several useful properties, including `this.userId`, which +identifies the currently logged-in user. ### Latency Compensation diff --git a/docs/client/basic/sections/session.md b/docs/client/basic/sections/session.md index c2fa070681..3faa011e07 100644 --- a/docs/client/basic/sections/session.md +++ b/docs/client/basic/sections/session.md @@ -6,13 +6,14 @@ store an arbitrary set of key-value pairs. Use it to store things like the currently selected item in a list. -What's special about `Session` is that it's reactive. If you call +What's special about `Session` is that it's _reactive_. If you call `Session.get("myKey")` in a [template helper](#template_helpers) or inside [`Tracker.autorun`](#tracker_autorun), the relevant part of the template will -automatically be re-rendered whenever `Session.set("myKey", newValue)` is +be re-rendered automatically whenever `Session.set("myKey", newValue)` is called. {{> autoApiBox "Session.set"}} + {{> autoApiBox "Session.get"}} @@ -40,9 +41,9 @@ Session.set("enemy", "Eurasia"); // Page will change to say "We've always been at war with Eurasia" ``` -Using `Session` gives us our first taste of "reactivity", the idea that the view -should update automatically when necessary, without us having to call a "render" +Using `Session` gives us our first taste of _reactivity_, the idea that the view +should update automatically when necessary, without us having to call a `render` function manually. In the next section, we will learn how to use Tracker, the lightweight library that makes this possible in Meteor. -{{/template}} \ No newline at end of file +{{/template}} diff --git a/docs/client/basic/sections/templates.md b/docs/client/basic/sections/templates.md index bdea2576c9..22e7383b77 100644 --- a/docs/client/basic/sections/templates.md +++ b/docs/client/basic/sections/templates.md @@ -8,15 +8,15 @@ which parts of the page are displayed.

Defining Templates in HTML

-Templates are defined in '.html' files that can be located anywhere in your +Templates are defined in `.html` files that can be located anywhere in your Meteor project folder except the `server`, `public`, and `private` directories. -Each HTML file can have any number of three types of top-level elements: +Each `.html` file can contain any number of the following top-level elements: ``, ``, or `