Syncronizing backbone with pusher - ruby-on-rails

I am writing an application using backbone + rails.
The application allows users to create tickets, and show these tickets in real-time for all other users using real-time service pusher.
My problem is that when a user creates a ticket I add it to the collection:
addTicket: function( newTicketData ) {
var newTicket = new app.Ticket( newTicketData );
this.collection.add(newTicket, {merge: true});
newTicket.save(null, {
wait: true,
success: this.addTicketSuccess,
error: this.addTicketError
});
},
The pusher listener code:
channel.bind('new_ticket', function(data) {
var ticketDataObj = jQuery.parseJSON( data.content );
app.ticketsView.addTicket(ticketDataObj);
});
In this point the new model has a cid but not an id from the database, which might be obtained in the addTicketSuccess callback.
On the other hand, the server sends a pusher signal in the create action which sends the new ticket with its id, but without id.
The result is two different models in the collection which represent the same object, one with cid and other with id. I am aware to the race-condition and looking for nice and robust solution.
Thanks!!!

The cid is a client id and is never send to the server.
When Backbone model save is called successfully the data received from the server are set on the same object, not creating another model.
So your are manually adding the two models to your collection, try to remove this line :
channel.bind('new_ticket', function(data) {
var ticketDataObj = jQuery.parseJSON( data.content );
// create a new method addAndMergeTicket
app.ticketsView.addAndMergeTicket(ticketDataObj);
});
In this new method, before you add the model to the collection, iterate through the collection models and if you find that it already exists don't add it again

Related

Change the document's unique ID from string to int in firebase realtime using xamarin form

My problem is I want to change the document/table unique ID from string to int in firebase realtime database.
This is how it looks in my database:
.
I want to look like this:
.
This is my code in inserting data to firebase:
public async Task<bool> Save(CUSTOMER customer)
{
//var token = await authProvider.CreateUserWithEmailAndPasswordAsync(customer.CusEmail,customer.CusPassword);&& !string.IsNullOrEmpty(token.FirebaseToken);
var token = await authProvider.CreateUserWithEmailAndPasswordAsync(customer.CusEmail, customer.CusPassword);
var data = await firebaseClient.Child(nameof(CUSTOMER)).PostAsync(JsonConvert.SerializeObject(customer));
if (!string.IsNullOrEmpty(data.Key) && !string.IsNullOrEmpty(token.FirebaseToken))
{
return true;
}
return false;
}
When you call PostAsync, Firebase creates a new child node with its own unique ID for that data. The IDs always have the form that you see in your first screenshot, and there's no way to change that.
To specify your own ID, generate that ID in your client-side application code, pass it to the API as an additional Child() call, and use Put instead of Post. For example:
firebaseClient.Child(nameof(CUSTOMER)).Child("4815").PutAsync(JsonConvert.SerializeObject(customer));
If the number you want to use is based on the existing keys in the database, you'll need to use a transaction to perform the necessary read-then-write sequence.
Since you're considering using numeric keys, I recommend checking out Best Practices: Arrays in Firebase.

Populating a ViewModel with the current form data before sending it off via JSON

I'm creating an ASP.NET MVC 5 SQL Server (Entity Framework, database-first) application where there is an order record and a set of line item records attached to it. I am using viewmodels to display the data. The user can add new line item records to the viewmodel through an "Add" button, but the line items are not committed to the database until the user clicks the "Save" button. (I've previously written about the application regarding a different issue: ASP.NET MVC - passing modified viewmodel from AJAX to view)
I have the "Add" button working fine... except for one very important use case. If the user changes some data in the web page then presses the "Add" button, none of the changes to the web page data are sent when the #Html.Raw(Json.Encode(Model)) line is called:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#mybutton").click(function () {
$.ajax({
url: "../AddNewLineItem/",
cache: false,
type: "POST",
data: {
'viewModel': #Html.Raw(Json.Encode(Model)),
},
success: function (data) {
$('#divPartial').append(data);
},
error: function (reponse) {
alert("Error: " + reponse);
}
});
});
});
</script>
Obviously, the reason why this is happening is because the model has not been updated with the latest data from the web page. However, how do I force the model to be updated before shipping it off via JSON? (Alternately, is there some way to always keep the viewmodel in sync with what the user has typed in the form?)
the Model object is a server-side entity that doesn't exist on the client. instead, you need to send the client data. try using jQuery's serialize method. this will take all elements in the form and turn it into an object that can be sent via the AJAX method:
data: {
'viewModel': $("form").serialize(),
},

Meteor Collections with Join using Iron Router

I have two Collections in Meteor, and trying to join them. As defined in collections/collections.js
Producers = new Mongo.Collection('producers');
Projects = new Mongo.Collection('projects');
Conceptually, one Producer has 0 to many Projects. One Project must have a Producer. So, a ProducerID field is in each Project document (row) in Mongo. I seeded the Mongo database with data.
When my template for viewing Projects is displayed, I want it to have access to the Producer's attributes.
In Iron Router's config (in /app.js), I have
Router.route('project', {
path: '/project/:name',
template: 'project',
waitOn: function() {
return Meteor.subscribe('ProjectInfo', this.params.name);
},
data: function() {
return Projects.find();
}
});
I have two publishes on the server (in /server/publish.js):
Meteor.publish("ProjectInfo", function(projectName) {
return Projects.find( {name: projectName} );
});
Meteor.publish("ProducerInfo", function(producerid) {
return Producers.find( {_id: producerid});
});
Question 1:
How to join? I definitely don't want to just throw Producer data into each Project, because it makes it harder to update the database when a Producer data changes.
Question 2:
Why does Iron Router need a "data:" field, when it already has a Subscribe in the waitOn?
data: function() {
return Projects.find();
}
Thanks in advance.
How to join: I'll just give you link to package doing just that: publish with relations
And you don't need data field when you publish, if your router loads OK and you have waitOn with publishes then on client side all your data should be visible when you do Producers.find() or Projects.find()
Although, waitOn requiers an array, so try
return [Meteor.subscribe('ProjectInfo', this.params.name)];

how to get an unsaved entity on server but not for saving?

i need to send my unsaved entity from the client to the server but not for saving changes
but inorder to do a process using the data on the entity and then change some of it's values and pass it back to the client
is this possible?
if not what are my options?
i tried to export the entity and then send it to a method on the webapi controller that gets a JObject but didn't find a way to deserialize it to the server entity
We did have a similar problem and found a solution as follows:
You need to take into consideration the way breeze manages it's objects.
1.Create custom saveBundle.
Consider complex order object.You need to fill your save bundle with each nested object inside order.
Like:
var saveBundle = new Array();
saveBundle.push(order.SaleAccountingInfo);
saveBundle.push(order.CostAccountingInfo);
saveBundle.push(order);
2.Create custom save options, where you can point to your custom Save Method on server
Like:
var so = new breeze.SaveOptions({ resourceName: "BookOrder" });
3.Call standard breeze function and pass it created params
manager.saveChanges(saveBundle, so).fail(function () {
// manager.rejectChanges();TODO check what needed
deferred.resolve(true);
});
On server you need to have you custom function ready and hook some breeze delegates
[HttpPost]
public SaveResult BookOrder(JObject orderBundle)
{
context.BeforeSaveEntityDelegate = OrderBeforeSaveEntity;
context.BeforeSaveEntitiesDelegate = SaveOrder;
context.AfterSaveEntitiesDelegate = BookOrderAfterSave;
try
{
return context.SaveChanges(orderBundle);
}
catch (Exception)
{
throw;
}
}
You can a lot of stuff in first two delegates but it is the last one you are looking for
private void BookOrderAfterSave(Dictionary<Type, List<EntityInfo>> orderSaveMap, List<KeyMapping> orderKeyMappings)
{
var orderEntity = orderSaveMap.Where(c => c.Key == typeof(BL.Orders.Order)).Select(d => d.Value).SingleOrDefault();
BL.Orders.Order order = (BL.Orders.Order)orderEntity[0].Entity; //your entity
//logic here
}
Hope it points to right direction.
we are doing something similar here. it'll save the entity so i'm not sure if this fits your question.
you can do:
entity.entityAspect.setModified()
then issue a saveChange()
then you can do your calculations on the server.
in our case we are using breeze.webapi so we are doing this in the beforeSave(entity) method.
breeze by design sends the changed entity then back to the client where the cache gets updated with your changes done on the server.

Custom DataService adapter saveChanges method to set entities to Unchanged

I've implemented a custom DataService adapter for BreezeJS - I wanted to use Breeze with a RESTful back end service (not OData or ASP.NET Web API).
So far - decent results after a learning curve.
I'm having an issue that when I call save changes - afterwards my entities on the client do not get marked as 'Unchanged'. They keep the same entityState.
I assume it has something to do with the success handler of the AJAX request to the backend service (looking at the source code to the WebAPI adapter):
success: function(data, textStatus, XHR) {
if (data.Error) {
// anticipatable errors on server - concurrency...
var err = createError(XHR);
err.message = data.Error;
deferred.reject(err);
} else {
// HACK: need to change the 'case' of properties in the saveResult
// but KeyMapping properties internally are still ucase. ugh...
var keyMappings = data.KeyMappings.map(function(km) {
var entityTypeName = MetadataStore.normalizeTypeName(km.EntityTypeName);
return { entityTypeName: entityTypeName, tempValue: km.TempValue, realValue: km.RealValue };
});
var saveResult = { entities: data.Entities, keyMappings: keyMappings, XHR: data.XHR };
deferred.resolve(saveResult);
}
},
It looks like the response includes an array of 'Entities'. What do these 'Entities' look like? It echoes what the client sent with an updated entityAspect.entityState value (server responses with 'Unchanged')?
Is that what should be passed into the deferred.resolve call?
I've got a working solution for this.
In a nutshell here's what is required for the object that is passed to the
deferred.resolve(saveResult);
Call in the success handler of the save change AJAX request.
Server response should include information about how to map from the client generated id to the server generated id (if the server generated one). This can be one keyMapping property returned in the response (like the Breeze API controller does) or what my service does is return a keyMapping property as a child property of a particular resource
The client code should create an array of objects that look like:
{ entityTypeName: "fully qualified entity type name",
tempValue: "client generated id",
realValue: "server generated id"
}
this array is the keyMappings property of the saveResult object
the entities property of the saveResult object is a flat list of all the entities that were modified from the server. Because of the design of my service API, it can return an entity, and child entities embedded in it, which I had to traverse and pull out into a flat list. Additionally these entity objects should be 'raw' and not include the entityAspect property or anything Breeze might interpret as a 'real' entity.
Also - something that can also be helpful is to look at the new sample from the Breeze folks - the MongoDB Breeze sample. They've implemented a custom dataServiceAdapter that hooks up their NodeJS/MongoDB backend. That provided some additional insight as well.
Good luck!

Resources