Skip to content

Instantly share code, notes, and snippets.

@ryanj
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanj/f2b8bda89e98f853caa2 to your computer and use it in GitHub Desktop.
Save ryanj/f2b8bda89e98f853caa2 to your computer and use it in GitHub Desktop.
Getting RESTless with MeteorJS
<section>
<section id="welcome" data-background-transition='zoom' data-transition='concave' data-background='http://ryanjarvinen.com/presentations/shared/img/broadcast_reveal_dark.png' data-state='blackout'>
<h2>Getting RESTless</h2>
<p>with</p>
<h1>Meteor</h1>
<br/>
<br/>
<p class='fragment'><small><a class='fragment' href='http://bit.ly/1s7TRzm'>bit.ly/1s7TRzm</a></small></p>
</section>
<section data-state="blackout">
<p>presented by</p>
<p><a href='http://ryanjarvinen.com/'>ryan jarvinen</a> / <a href='http://twitter.com/ryanj/'>@ryanj</a></p>
<a href="http://ryanjarvinen.com"><img src="http://ryanjarvinen.com/presentations/shared/img/moo_openshift_horizontal.png"/></a>
</section>
<section id="eventbrite" data-background-transition='zoom' data-transition='linear' data-markdown>
Used to run the developer program at [Eventbrite](http://developer.eventbrite.com)
</section>
<section id="secondlife" data-background-transition='zoom' data-transition='linear'>
<a href="https://join.secondlife.com/"><img src="http://secondlife.com/_img/new/img-logo.png"/></a>
<p>Realtime, multi-user experiences</p>
</section>
<section id="nodejs" data-background-transition='zoom' data-transition='linear' data-markdown>
## nodejs
![oaklandjs](http://d21ii91i3y6o6h.cloudfront.net/gallery_images/from_proof/1504/large/1403129381/oakland-dot-js.png)
</section>
<section id="CFA" data-background-transition='zoom' data-transition='linear' data-markdown>
## code for america
code for Oakland
</section>
<section id="sudoroom" data-background-transition='zoom' data-transition='linear' data-markdown>
## [sudoroom](http://sudoroom.org)
![sudoroom](https://sudoroom.org/wp-content/uploads/2014/04/sudoroom_logo_small.png)
</section>
<section id="cryptoparty" data-background-transition='zoom' data-transition='linear'>
<h2>cryptoparty</h2>
<a href="https://twitter.com/oakcryptoparty"><img src="https://pbs.twimg.com/profile_images/2718093368/c10422f91155cb7ef52373beef5ebe0a.png"/></a>
<br/>
<ol>
<li>&lt;3 EFF, digital rights</li>
<li>fully homomorphic encryption</li>
<li>tahoe-LAFS</li></ol>
</ol>
</section>
<section id="devadvocates" data-background-transition='zoom' data-transition='linear'>
<h2>Developer Advocates</h2>
<a href="http://www.meetup.com/developeradvocates/"><img src="http://photos1.meetupstatic.com/photos/event/2/4/9/1/global_43689361.jpeg"/></a>
<br/>
<a href="http://www.meetup.com/members/5799882/">one of 87 meetup groups</a>
</section>
</section>
<section data-background-transition='zoom' data-transition='linear'>
<section id="agenda" data-background-transition='zoom' data-transition='linear'>
<h1>Agenda</h1>
<ul>
<li class='fragment roll-in'>Intro to Meteor</li>
<li class='fragment roll-in'>Build a basic Meteor app</li>
<li class='fragment roll-in'>Test Client-Side Security for Meteor</li>
</ul>
</section>
<section id="requirements" data-markdown>
### Requirements:
Install [Meteorjs](https://www.meteor.com/) and [MongoDB](http://www.mongodb.com/)
curl https://install.meteor.com/ | sh
</section>
<section id="example-code" data-markdown>
Code du Jour
[https://github.com/ryanj/meteor-showcase](https://github.com/ryanj/meteor-showcase)
</section>
</section>
<section>
<section>
<h1>Meteor</h1>
<div class="fragment roll-in">is&hellip;</div>
<div class="fragment roll-in"><a href='http://docs.meteor.com/#sevenprinciples'>&lt;seven principles&gt;</a></div>
</section>
<section>
<h1>Data on the Wire</h1>
<div class="fragment roll-in">Don't send HTML over the network.<br/>Just send data, let the client decide how to render it.</div>
</section>
<section>
<h1>One Language</h1>
<div class="fragment roll-in">Javascript</div>
</section>
<section>
<h1>Database Everywhere</h1>
<div class="fragment roll-in">Use the same APIs on the client and the server.</div>
</section>
<section>
<h1>Latency Compensation</h1>
<div class="fragment roll-in">On the client, use prefetching and model simulation to make it look like you have a zero-latency connection to the database.</div>
</section>
<section>
<h1>Full Stack Reactivity</h1>
<div class="fragment roll-in">Make realtime your default.<br/>All layers from DB to templates should make an event-driven interface available.</div>
</section>
<section>
<h1>Embrace the Ecosystem</h1>
<div class="fragment roll-in">Meteor is Open Source and integrates with existing open source tools and frameworks (rather than replacing them).</div>
</section>
<section>
<h1>Simplicity Equals Productivity</h1>
<div class="fragment roll-in">The best way to make something seem simple is to have it actually be simple.</div>
</section>
</section>
<section>
<section>
<h1>How?</h1>
</section>
<section>
<h2>fibers</h2>
<p><a href="https://meteorhacks.com/fibers-eventloop-and-meteor.html">Fibers, the Event Loop and Meteor</a></p>
<p>source: <a href="https://github.com/laverdet/node-fibers/">node-fibers</a></p>
</section>
<section>
<h2><span class='fragment roll-in'>Smart</span> Packages</h2>
<pre><code contenteditable>meteor add bootstrap
meteor add handlebars
meteor add jquery
meteor add underscore
meteor add service-configuration
meteor add accounts-github
meteor remove insecure</code></pre>
</section>
<section>
<h2>Pre-9.0</h2>
<h3>meteorite</h3>
<pre><code contenteditable>npm install --global meteorite</code></pre>
<p class='fragment'>no longer needed!</p>
</section>
<section>
<h2>New: Meteor package system</h2>
<p class='fragment'>Meteor 9.x includes a new Meteor package system (featuring Isobuild, Meteor Package Server)
</p>
<ul>
<li class='fragment'>publish your own packages</li>
<li class='fragment'>over 1800 community packages</li>
</ul>
<pre class='fragment'><code contenteditable>meteor add &lt;packagename&gt;</code></pre>
<pre class='fragment'><code contenteditable>meteor publish</code></pre>
<pre class='fragment'><code contenteditable>meteor search &lt;query&gt;</code></pre>
</section>
</section>
<section>
<section>
<h1>Let's look at some code<span class='fragment roll-in'>!</span></h1>
<a href='https://github.com/ryanj/meteor-showcase'>https://github.com/ryanj/meteor-showcase</a>
</section>
<section>
<h2>Client code and Server code</h2>
<pre><code contenteditable>if (Meteor.isServer) {
...
}</code></pre>
<pre><code contenteditable>if (Meteor.isClient) {
...
}</code></pre>
</section>
<section>
<pre><code contenteditable>Showcase = new Meteor.Collection("showcase");
if (Meteor.isServer) {
Meteor.publish("showcase-items", function () {
return Showcase.find(); // share everything in the showcase
});
}
if (Meteor.isClient) {
Meteor.subscribe("showcase-items");
}</code></pre>
</section>
</section>
<section>
<section id='templating' data-markdown>
# templates
</section>
<section>
<h2>Templates (HTML)</h2>
<pre><code contenteditable>&lt;head&gt;
&lt;title&gt;meteorshowcase&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
{{&gt; nav}}
{{&gt; list}}
{{&gt; submit}}
{{&gt; edit}}
{{&gt; view}}
&lt;/body&gt;</code></pre>
</section>
<section>
<h2>Templates (HTML)</h2>
<pre><code contenteditable> &lt;template name="list"&gt;
&lt;div class="showcase"&gt;
{{#each items}}
{{&gt; item}}
&lt;hr/&gt;
{{/each}}
&lt;/div&gt;
&lt;/template&gt;
</code></pre>
</section>
<section>
<h2>Templates (HTML)</h2>
<pre><code contenteditable>&lt;template name="view"&gt;
&lt;div id='modal_view' class="modal fade in"
&lt;div class="modal-header"&gt;
&lt;a href="#" data-dismiss="modal" class="close pull-right;"&gt;&times;&lt;/a&gt;
&lt;h3 class="item_title"&gt;{{app_name}}&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="modal-body"&gt;
&lt;div class'image_url'&gt;&lt;a href='{{demo_url}}'&gt;&lt;img src='{{image_url}}'/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class='name'&gt;{{app_name}}&lt;/div&gt;
&lt;div class='description'&gt;{{description}}&lt;/div&gt;
&lt;div class='authored_by'&gt;By: &lt;span class='author'&gt;{{author}}&lt;/span&gt;&lt;/div&gt;
&lt;div class='date'&gt;Submitted on: {{date}}&lt;/div&gt;
&lt;div class='score'&gt;Score: {{score}}&lt;/div&gt;
&lt;div class='source_url'&gt;Source code: &lt;a href='{{source_url}}'&gt;{{source_url}}&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="{{clone_url}}" class="shift btn btn-large btn-inverse btn-block"&gt;Run on OpenShift &lt;b class='icon-cog'&gt;&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="modal-footer"&gt;
{{# if currentUser }}&lt;a href="#" $('#modal_edit').modal('show') &amp;&amp; $('#modal_view').modal('hide');" class="edit pull-left btn btn-info"&gt;Settings &lt;b class='icon-wrench'&gt;&lt;/b&gt;&lt;/a&gt;{{/if}}
&lt;a href="{{demo_url}}" onclick="console.log('Opening app...');" class="pull-right btn btn-primary"&gt;Visit &lt;b class='icon-globe'&gt;&lt;/b&gt;&lt;/a&gt;
&lt;a href="#" data-dismiss="modal" onclick="$('#modal_view').modal('hide');" class="btn pull-right"&gt;Cancel &lt;b class='icon-remove'&gt;&lt;/b&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
</code></pre>
</section>
<section>
<h2>Templates (js)</h2>
<pre><code contenteditable>Template.list.items = function () {
var nav_config = Session.get('nav_settings');
var sort_by = Session.get('sort_by');
var sort_order = {};
var filter = Session.get('filter');
if (!filter || filter == undefined){ filter = '' };
sort_order[sort_by] = nav_config[sort_by] || -1;
return Showcase.find({ name: { $regex: filter, $options: 'i'}}, {sort: sort_order}).fetch();
};
Template.nav.username = function () {
var u = Meteor.user();
return u &amp;&amp; u.profile &amp;&amp; u.profile.name;
};</code></pre>
</section>
<section>
<h2>Events</h2>
<pre><code contenteditable>Template.item.events({
'click a.inc': function () {
Showcase.update(Session.get("selected_item"), {$inc: {score: 5}});
},
'click a.dec': function () {
Showcase.update(Session.get("selected_item"), {$inc: {score: -5}});
},
'click a.view': function () {
$('#modal_view').modal('show');
}
});
</code></pre>
</section>
</section>
<section>
<section>
<h2>Protecting DB Access</h2>
<pre><code contenteditable>Showcase.allow({
remove: function (userId, item) {
var username = false;
if(userId){
username = Meteor.users.findOne(userId).profile.name;
}
return (item.author == username || username == 'ryan jarvinen');
},
insert: function (userId, item) {
return (userId) ? true : false;
},
update: function (userId, item, fieldNames, modifier) {
</code></pre>
</section>
<section>
<pre><code contenteditable>update: function (userId, item, fieldNames, modifier) {
var username = false;
if(userId){
username = Meteor.users.findOne(userId).profile.name;
}
if(item.score &gt; 9000){
// OVER 9000?!?!
return false;
}else if( _.isEqual(modifier, {$inc:{score: +5}})){
//allow voting by anyone
console.log('option1 - voter');
return true;
}else if( _.isEqual(modifier, {$inc:{score: -5}}) &amp;&amp; item.score &gt; 4 ){
//allow voting by anyone
console.log('option1 - voter');
return true;
}else if(username == 'ryan jarvinen') {
//allow updates by admins (me) :-P
console.log('option2 - admin');
return true;
}else{
//allow updates by owners
console.log('option3 - owner');
return ( username == item.author ) ? true : false;
}
}</code></pre>
</section>
</section>
<section>
<section>
<h2>3rd party auth</h2>
<pre><code contenteditable>var github_client_id = process.env.GITHUB_CLIENT || 'cc02855bd41dbfc4be72';
var github_client_secret = process.env.GITHUB_SECRET || '443ea5d64be6afada4acd946cf5b49878f4af4c8';
ServiceConfiguration.configurations.remove({
service: "github"
});
ServiceConfiguration.configurations.insert({
service: "github",
clientId: github_client_id,
secret: github_client_secret
});</code></pre>
</section>
</section>
<section>
<section>
<h2>Shipping Meteor</h2>
<p>to meteor.com:</p>
<pre><code contenteditable>meteor deploy</code></pre>
</section>
<section>
<h3>Production flag</h3>
<pre><code contenteditable>meteor --production</code></pre>
</section>
<section>
<h2>Bundles</h2>
<pre><code contenteditable>meteor bundle bundle.tar.gz</code></pre>
</section>
<section>
<h2>Docker Images</h2>
<a href="https://registry.hub.docker.com/search?q=meteor">https://registry.hub.docker.com/search?q=meteor</a>
</section>
</section>
<section>
<section id="links" data-markdown>
## Want More Info?
1. [meteor.com](http://meteor.com/)
2. [meteorhacks.com](https://meteorhacks.com/)
3. [unofficial meteor FAQ](https://github.com/oortcloud/unofficial-meteor-faq)
4. [meteor on StackOverflow](https://stackoverflow.com/questions/tagged/meteor)
5. [Free, open source, nodejs hosting on openshift.com](https://www.openshift.com/)
</section>
<section id="thank-you" data-state="blackout">
<p><b><i>Thanks for following along! &nbsp; --ryanj</i></b></p>
<p>link to slides:</p>
<p><a href="http://bit.ly/1s7TRzm">bit.ly/1s7TRzm</a></p>
</section>
</section>
@ryanj
Copy link
Author

ryanj commented Oct 1, 2014

Update: Meteor 0.9.3.1 is out!

The Meteor package system has gotten a major upgrade and is now fully integrated and officially supported by the Meteor core team (you no longer need to install Meteorite)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment