Last active
December 12, 2015 01:18
-
-
Save lancejpollard/4689443 to your computer and use it in GitHub Desktop.
Brain dumping on adapters.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // associating properties from different apis with your model. | |
| // say, by default if the associated fields are blank, it will | |
| // fetch and save them from the service. | |
| // `linkedIn.resume` has similar API meaning to `DS.attr('App.Company')` | |
| adapter('linkedIn') | |
| .resource('resume') | |
| .mixin({ | |
| find: function(criteria, callback) { | |
| // criteria == | |
| /* [ | |
| * ['resume', 'resume'] // only passed to linkedIn adapter | |
| * , ['photoUrl', 'user', 'photoUrl'] // only passed to facebook adapter | |
| * ]] | |
| */ | |
| this.get('http://api.linkedIn.com/resume', function(callback) { | |
| }); | |
| } | |
| }) | |
| adapter('twitter') | |
| .resource('user') | |
| .resource('tweet') | |
| .mixin({ | |
| /* | |
| * [ | |
| * ['user', 'profile_image_url'] | |
| * , ['user', 'email'] | |
| * ] | |
| */ | |
| find: function(criteria) { | |
| } | |
| }) | |
| adapter('facebook') | |
| .resource('user') | |
| .resource('status') | |
| .resource('page') | |
| .resource('app') | |
| .mixin({ | |
| /* | |
| * [['user', 'photoUrl']] | |
| */ | |
| find: function(criteria) { | |
| } | |
| }) | |
| model('user') | |
| .field('resume', 'linkedIn.resume') | |
| .field('photoUrl', 'facebook.user.photoUrl') | |
| .field('photoUrl', { | |
| // in this case it may try facebook first, then twitter if nothing found | |
| sources: [ | |
| 'facebook.user.photoUrl' | |
| , 'twitter.user.profile_image_url' | |
| ] | |
| }) | |
| .field('photoUrl', { | |
| // or maybe they need to be, themselves, controllers (or, better, criteria) | |
| sources: [ | |
| criteria('facebook.user').select('photoUrl') | |
| , criteria('twitter.user').select('profile_image_url') | |
| ] | |
| }) | |
| // since `twitter.user` is used more than once, the adapter will have the `twitter` | |
| // object cached in there so it won't need to make another call. | |
| .field('email', 'twitter.user.email') | |
| .index('id', {in: 'redis'}) | |
| // somehow you'd have to know what to pass to the adapter | |
| // (facebook/linkedin credentials, etc.) | |
| controller('user').create(function(error, user) { | |
| assert(user.get('resume')); | |
| assert(user.get('photoUrl')); | |
| }); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Still figuring out the final end pieces. But I think the biggest thing is mentally breaking away from the way Rails used controllers (that's why I'm liking writing in lowercase like
controller('users'), it makes the controllers feel lighter and I can step out of the Rails mindset). Instead, controllers are basically representations of the data; controllers or the ways you manipulate/query/compute/create/destroy data. In this new sense, controllers have arbitrary names, such ascontroller('unreadMessagesCount'), but there are also default controller classes that are created for (1) every route in the system (e.g.controller('users.index')forroute('/users', 'users.index')), (2) every model in the system (e.g.controller('user')) which I'm thinking as of now will only really be used on the client for formatting the field values (that was the i18n stuff earlier today), and (3) every model plural (collection) in the system (e.g.controller('users')). There seems like there some overlap (i.e.controller('users.index')andcontroller('users')seem like they should probably do the same thing). But, this is where the convention for using controllers comes in. Since there is a controller for every route, you should choosecontroller('users.index')overcontroller('users')because the route-specific controller comes packed with extra stuff specific to the route. For example, you can specify specific parameters to be parsed on that route, and if they are found, to be appended to the route's controller'scriteria. An example is:route('posts.index').param('title').setup(function(controller) { controller.all() })..., where thatcontroller.all()call will be passingcriteriato the store that contains whatever the query parameter value was for "title", such as['field', 'title', 'match', 'the passed value']). In addition, the criteria passed to the store fromcontroller.all()could also contain user-specific conditions, such as authorization rules for what the user can see. This is the reason you'd pick route-specific controllers over the model-plural controllers likecontroller('posts'). For each of these route-specific controllers likecontroller('posts.index')andcontroller('posts.create'), the first clause in the criteria is going to be['start', modelName], which tells the adapter what table/collection to use. Now for controllers likecontroller('unreadMessagesCount'), which don't map to a specific model (at least we can't infer that based on the name), you have to specify thestartcriteria (start/extend), so realistically it would look more likecontroller('unreadMessagesCount').start('messages').where('read', false). This is how graph query languages work, specifying the "start node". Then thatreturns('count')tells the controller to return an integer rather than a record (or array of records). So, this controller doesn't map neatly to a model -- this is why removing the ideas of Rails controllers is helpful -- the controller, instead, is just a representation of the data, a controller for the data.This also means the idea of a
modelis more flexible than Rails. Models are basically your database tables, but they're there more to just save your data in an easy-to-query and easy-to-represent way. The controllers are the interface to the models, and so, the only time you ever usemodel('user')is in defining the model -- creating the schema. To access the model, you use a controller. This is very different than Rails, where you access data from the model as inUser.all, but it offers much much more power.The center of the app, then, is the idea of "resources" more than it is "models". You need models to structure your data so you can persist/query it easily. But you define a set of "routes" for the user/client, and you use controllers to optimally feed different representations of the models to the client.