JS Persistence library that will PATCH only changed values - javascript

I am evaluating JS persistence libraries. I'm on an Angular stack so ngResource and Restangular are options, but so are Breeze and Backbone's Models/collections and I'm open to others.
Is there a JS persistence library out there that will monitor changes to the model and do a PATCH of only the changed properties?
Example:
// Get a pretend user with a name, email, and some other stuff.
var currentUser = user.get(42)
// Change only the email address
currentUser.email = 'tractorDaddy#aol.com'
// Save changes
// The model could know that only one property has changed.
// The model could do a PATCH of a partial object, but I don't know a library that does.
currentUser.save()
This seems like it should be the default implementation but none of these libraries do it, that I could see.
Backbone's model decides whether to POST or PUT based on the newness of the model (determined by presence of id, as I recall). I think this is a nice move and could be extended to include PATCH.
I understand that Restangular and others have a .patch() method, but I believe in all cases you have to specify the object partial explicitly.
Is there a library that does this?

I think there is no existing JS model/persistence layer that will track and PATCH only change values.
I have high hopes for AngularJS 2.0's data layer: http://tinyurl.com/pa7rxf8

Related

Best practice to change default blueprint actions in sails.js

I'm looking for an answer to what is the best practice to customize default sails.js CRUD blueprints. The simple example of what I mean is let's say I need to create SomeModel, using standard blueprint POST \someModel action, and also I want to get information about authenticated user from req object and set this property to req.body to use values.user.id in beforeCreate function:
module.exports = {
attributes: {
// some attributes
},
beforeCreate: function (values, cb) {
// do something with values.user.id
}
};
I'm very new to sails.js and don't want to use anti-patterns, so I'm asking for inputs on what is the right way to handle such cases. Also it would be great to have some good resources on that topic.
There are a few options open to you which you've identified, and as usual, it depends on your use case. Here are some thoughts on the three options you listed in your comment:
Override controller/create - Of the three, this is the best option because it doesn't clog up code in routes or policies for a single instance.
Write controller/action and add to config/routes.js - While this works, it defeats the purpose of using blueprints, and you have to do all the code in option 1 plus making your routes code messier.
Apply a policy for a single create action - To do this, you will not only have to clutter up your /policies folder but also your policies.js file. This is more code AND it puts the logic for one controller method in two separate places, neither of which is the controller.
Out of these three, option 1 is the best because it contains the code to its context (the controller) and minimizes written code. This is assuming that you only want to alter the create method for one model.
Side note:
As an example of how your use case determines your implementation, here is how I've set my Sails app up which has a few REST routes, each of which responds differently based on the user calling the route (with a valid Facebook token):
Only uses blueprint action routes (not blueprint REST routes)
First goes through the policies:
'*': ['hasFBToken', 'isTokenForMyApp', 'extractFBUser', 'extractMyAppUser'] which store fbuser, myappuser, and other variables in req.body
At this point, my controller function (e.g. controller.action()) is called and can access information about that user and determine if it has the correct permissions to do CRUD.
Pros of this system:
All code for each CRUD operation is contained within its controller function
Minimal to no code in routes.js (no code) or policies.js (one line) or /policies
Works well with API Versioning (e.g. controllers/v1.0/controller.js), which is much easier to do with versioned controllers than versioned models. That means that I can create a new API version and simply by creating a controller in /v2.0 with a function action(), calls such as POST /v2.0/controller/action will exist with no extra routing needed.
Hopefully this example helps illustrate how design decisions were made to offer functionality like API versioning and consolidate code in its specific context.

SailsJS blueprint matching wrong model

I'm having a tricky issue with my models and Sails' automatic blueprint matching.
When I post to one of my endpoints, /answer/create, I get a 500 response with validation errors for a different model entirely (the event model).
That endpoint for the event model would be at /event/create, but when I post to that I get a 404.
All of my files were generated with sails generate [model] and don't contain any custom Controller routes.
Has anyone seen this before?
It turned out this was a result of following this screencast:
http://irlnathan.github.io/sailscasts/blog/2013/09/15/sailscasts-answers-ep1-question-about-using-a-service-to-allow-inheritance-in-a-model/
I was inheriting a baseModel via services into more than one other model, so when I ran _.merge(), the changes it made would persist across them both, rendering inconsistencies.
If you want to do this, make sure you use the _.cloneDeep method to clone the base model, otherwise _.merge will affect it and your blueprints/actions won't work as expected.
In the screencast above, this would make line 12 in the user model look like this:
module.exports = _.merge(_.cloneDeep(baseModel) { ... });

Reusing data between ViewModels in knockout.js

I have an array of items populated by an AJAX call in a knockout ViewModel, which displays a few fields of data for each item on a web page.
Now I need to enable the user to click on one item populating a side bar with data which was received from the previous AJAX request (a few fields plus a lot more).
I suppose typically one would take an id and do an item specific AJAX request, routing it through Sammy.js, but we don't need to.
I'm new to knockout; best policy I imagine is to have a ViewModel for the various divs to display the data, but how to get the ViewModels to pass data between themselves? Is this taboo?
Making reference to the other window via the window object?
Using the with: keyword? It keeps cropping up, but I can't see how to apply that in this context.
Perhaps going via Sammy.js, and caching the data in Amplify?
This is an example of drill-down functionality, and I've read a number of StackOverflow Q&A about this but couldn't find up something I can use. I've got up to this stage by following John Papa's PluralSight tutorial.
You may want to go with a pub/sub model either with Amplify's messaging or the library the #RPNiemeyer mentions above. Both are excellent.
However it sounds like you just want to grab the data from the server, then use that data in multiple view models. Perhaps even sharing some of that data in multiple view models. The datacontext concept in my SPA tutorial allows you to host data in the datacontext and reference it from other view models.
You could also use a library like Breeze to help do this (Breeze would replace the datacontext in my SPA ... and be better at it as I will show in an upcoming course).
These are just a few options
You may also want to checkout the "Share an EntityManager" post under "Cool Breezes" in the breeze documentation.
The sharing a single EntityManager is probably all you need. But if you think you need more than one, read "Multiple managers".
IMO The easiest way to do it is to simply pass "params" with an observable containing data to your sidebar component.
http://knockoutjs.com/documentation/component-custom-elements.html#passing-observable-expressions
As was mentioned in comments, the good choice would be to use knockout-postbox
knockout-postbox is a Knockout.js plugin designed to use Knockout's basic pub/sub capabilities to facilitate decoupled communication between separate view models / components.
This allows you to set up simple topic-based communication like:
var ViewModelOne = function() {
this.isEditable = ko.observable();
};
var ViewModelTwo = function() {
this.editable = ko.observable(false);
};
var one = new ViewModelOne();
var two = new ViewModelTwo();
var editableTopic = "myEditableTopic";
one.isEditable.subscribeTo(editableTopic);
two.editable.publishOn(editableTopic)

ExtJS - How to use Proxy, Model? How are they related?

I've been trying to learn to work with Models and Stores. But the proxy bit is confusing me a lot. So I'm going to list out my understanding here - please point out the gaps in my understanding.
My understanding
Models are used to represent domain objects.
Models can be created by ModelManager, or by simply using the constructor
Models are saved in Stores
Stores may be in memory stores, or can be server stores. This is configured using Proxy.
Proxy tells the store how to talk to a backing store - be that a JSON array, or a REST resource, or a simply configured URL via ajax.
Stores are responsible for storing models, and Proxies are responsible for controlling/helping with that task.
When a model's values are changed, its dirty flag gets set. It gets automatically cleared when the model is saved. (more in this later)
The part that confuses me
Why is there a proxy config and save method on Model? I understand that models can only be stored on to stores.
Why is the dirty flag not cleared simply when I add a model object to a store?
When I add a model object to a store, why does the model not acquire the proxy configured with that store?
proxy is a static configuration for a Model. Does that mean that we cannot use objects of a particular model with multiple data sources? By extension, does this mean having multiple stores for a single model essentially useless?
When we define a Store, are we defining a class (store-type, if we may call it that), or is it an instance of a store? Reason I ask is when we declare a grid, we simply pass it a store config as store: 'MyApp.store.MyStore' - does the grid instantiate a grid of that type, or is it simply using the store we've already instantiated?
Thanks!
PS: +50 bounty to the person who explains all this :) - will offer bounty after those 48 hours are over..
The docs say:
A Model represents some object that your application manages.
A Store is just a collection of Model instances - usually loaded from a server somewhere.
Models are saved in Stores
Not only. The Models can be used separately (f.i. for populating forms with data. Check out Ext.form.Panel.loadRecord for more info).
Why is there a proxy config and save method on Model? I understand that models can only be stored on to stores.
As I've said, not only.
Why is the dirty flag not cleared simply when I add a model object to a store?
Why should it? The Record becomes clean only when it gets synchronized with the corresponding record on the server side.
When I add a model object to a store, why does the model not acquire the proxy configured with that store?
This is, again, because model can be used without store.
proxy is a static configuration for a Model. Does that mean that we cannot use objects of a particular model with multiple data sources?
We cannot use objects of a particular model but we can use one model definition for multiple store. For example:
Ext.define('MyModel', {
// ... config
});
var store1 = Ext.create('Ext.data.Store', {
model: 'MyModel',
// ... config
proxy: {
// ...
// this proxy will be used when store1.sync() and store1.load() are called
}
// ...
});
// ...
var storeN = Ext.create('Ext.data.Store', {
model: 'MyModel',
// ... config
proxy: {
// ...
// this proxy will be used when storeN.sync() and storeN.load() are called
}
// ...
});
Since store1 and storeN use different proxies, the records, contained by these stores, may be completely different.
When we define a Store, are we defining a class (store-type, if we may call it that), or is it an instance of a store?
Yes, when we define a Store, we are defining a class.
Reason I ask is when we declare a grid, we simply pass it a store config as store: 'MyApp.store.MyStore' - does the grid instantiate a grid of that type, or is it simply using the store we've already instantiated?
There are couple of ways to set store config for grid:
store: existingStore,
store: 'someStoresId',
store: 'MyApp.store.MyStore',
In the first and the second cases existing instances of stores would be used. In the third case newly created instance of 'MyApp.store.MyStore' would be used. So, store: 'MyApp.store.MyStore', is equal to
var myStore = Ext.create('MyApp.store.MyStore', {});
// ...
// the following - is in a grid's config:
store: myStore,
UPDATE
When a model is added to store and then the store's sync() is called, why is the model's dirty flag not cleared?
It should be cleared, unless reader, writer and server response are not set up properly. Check out writer example. There is dirty flag being cleared automaticaly on store's sync().
if a model class is not given any proxy at all, why does it track its dirty status?
To let you know if the record was changed since the creation moment.
What is achieved by introducing the concept of Models syncing themselves to the server?
Let's assume you are creating a widget which contains plain set of inputs. The values for this inputs can be loaded from db (this set of inputs represents one row in db table). And when user changes the inputs' values data should be sent to the server. This data can be stored in one record.
So what would you use for this interface: one record or a store with only one record?
Standalone model - is for widgets that represent one row in db table.
Store - is for widgets that represent set of rows in db table.
I'm coming from ExtJS 2.2 [sic] to 4, and the Model behavior and terminology threw me for a loop too.
The best quick explanation I can find is from this post in the "Countdown to ExtJS 4" series on Sencha's blog. Turns out a Model acts like it does because it's "really" a Record.
The centerpiece of the data package is Ext.data.Model. A Model
represents some type of data in an application - for example an
e-commerce app might have models for Users, Products and Orders. At
its simplest a Model is just a set of fields and their data. Anyone
familiar with Ext JS 3 will have used Ext.data.Record, which was the
precursor to Ext.data.Model.
Here's the confusing part: A Model is both a model for the data you're using and a single instance of an object following that model. Let's call its two uses "Model qua model" and "Model qua Record".
This is why its load method requires a unique id (full stop). Model qua Record uses that id to create RESTful URLs for retrieving (and saving, etc) a single Record worth of data. The RESTful URL convention is described here and is linked to in this post on Sencha's blog that talks specifically about Model usage.
Here are a few RESTful URLs formed to that standard to get you familiar with the format, which it appears ExtJS' Model does use:
Operate on a Record with id of 1
GET /people/1 <<< That's what's used to retrieve a single record into Model
return the first record with id of 2
DELETE /people/2
destroy the first record with id of 7
POST /people/7?_method=DELETE
Etc etc.
This is also why Models have their own proxies, so that they can run RESTful operations via that URL modified to follow the conventions described in that link. You might pull 100s of records from one URL, which you'd use as your Store's proxy source, but when you want to save what's in the single Model (again, think "Model qua Record" here), you might perform those Record-specific operations through another URL whose backend messes with one record at a time.
So When Do I use Stores?
To store more than one instance of that Model, you'd slap them into a Store. You add lots of Models qua Records into Stores and then access those "Models" to pull data out. So if you have a grid you'll naturally want to have all that data locally, without having to re-query the server for each row's display.
From the first post:
Models are typically used with a Store, which is basically a
collection of Model instances.
And, of course, the Stores apparently pull info from Model qua Model here to know what they're carrying.
I found it in the documentation of sencha App Architecture Part 2
Use proxies for models:
It is generally good practice to do this as it allows you to load and
save instances of this model without needing a store. Also, when
multiple stores use this same model, you don’t have to redefine your
proxy on each one of them.
Use proxies for stores:
In Ext JS 4, multiple stores can use the same data model, even if the
stores will load their data from different sources. In our example,
the Station model will be used by the SearchResults and the Stations
store, both loading the data from a different location. One returns
search results, the other returns the user’s favorite stations. To
achieve this, one of our stores will need to override the proxy
defined on the model.

Apply Backbone.js for multi-module Javascript Website

I am writing a module based javascript website, backed by a Mysql DB.
Each module talks with the DB through PHP.
On the UI, for simplicity, the module on the left will display all relevant rows, with edit(write) functionality. The module on the right display the data from the same DB, with write access too.
So each would affect the other in each update.
I'm told backbone would be a good framework. Then, I have read the todos example, and understand how there are item->itemList, view->viewList, etc...
But now, the question is, how do I apply it to this situation?
Which is an item, a view in this situation?
The module on the left and the module on the right are Views, each of which can be made up of other views.
Within the model don't store a reference to the view (as I've seen done in some of the examples):
this.view = view; //view being passed in as an arg
The reverse (a view storing a reference to a model) is okay. Your views should be doing most of the work, listening to and responding to model events. Thus, in the view initialize method you might:
model.bind("interesting-event", function(){
//the view updates/reacts to the model.
});
Also, never add a model to two collections (just one ever). When a model is assigned to a collection, Backbone sets a reference on the model that points to the owning collection.
Incidentally, the a-model-cannot-belong-to-two-collections issue is the reason why you don't want a model referencing its view. A model can have many views on one screen.
Backbone is perfect for your needs. Start with a very basic version of your app and keep fleshing it out. All the while keep reading about Backbone online. I read everything I could find (there's not a whole lot, not really). The key concept is simply event based programming (much like you'd use in VB or lots of other platforms). It's a lot of trial and error, but you'll make sense of it with practice.

Categories