Marionette - backbone how to use fetch correctly - backbone.js

This is a simple question but I can's see it answered in the Marionette Wiki.
If I load data into a Collection via a url what format does that data have to be in?
Does it have to have an ID like this:
[
{id: "something", name: "Justin", hobbies: ""},
{id: "something2", name: "Fred", hobbies: ""}
]
Is the ID field required for it to work properly?

Yes, you should have an id attribute: Backbone determines whether the model instance has been persisted on the remote server by checking whether it has an id value or not.
if it has an id => use HTTP PUT verb to cause an update
if it doesn't have an id => use HTTP POST verb to create a new record

We do not use id field in our data set so it is not a 'must'. We also manage when to use POST or PUT directly from the client code and not relying on backbone to do it automatically.
model.save(..., {type: 'POST'});
model.save(..., {type: 'PUT'});

Related

Meteor inserting into a collection schema with array elements

Hi I created a SimpleSchema for a Mongo collection which has a variable number of sub-documents called measurables. Unfortunately it's been a while since I've done this and I can't remember how to insert into this type of schema! Can someone help me out?
The schema is as follows:
const ExerciseTemplates = new Mongo.Collection('ExerciseTemplates');
const ExerciseTemplateSchema = new SimpleSchema({
name: {
type: String,
label: 'name',
},
description: {
type: String,
label: 'description',
},
createdAt: {
type: Date,
label: 'date',
},
measurables: {
type: Array,
minCount: 1,
},
'measurables.$': Object,
'measurables.$.name': String,
'measurables.$.unit': String,
});
ExerciseTemplates.attachSchema(ExerciseTemplateSchema);
The method is:
Meteor.methods({
addNewExerciseTemplate(name, description, measurables) {
ExerciseTemplates.insert({
name,
description,
createdAt: new Date(),
measurables,
});
},
});
The data sent by my form for measurables is an array of objects.
The SimpleSchema docs seem to be out of date. If I use the example they show with measurables: type: [Object] for an array of objects. I get an error that the the type can't be an array and I should set it to Array.
Any suggestions would be awesome!!
Many thanks in advance!
edit:
The measurable variable contains the following data:
[{name: weight, unit: kg}]
With the schema above I get no error at all, it is silent as if it was successful, but when I check the db via CLI I have no collections. Am I doing something really stupid? When I create a new meteor app, it creates a Mongo db for me I assume - I'm not forgetting to actually create a db or something dumb?
Turns out I was stupid. The schema I posted was correct and works exactly as intended. The problem was that I defined my schema and method in a file in my imports directory, outside both client and server directories. This methods file was imported into the file with the form that calls the method, and therefore available on the client, but not imported into the server.
I guess that the method was being called on the client as a stub so I saw the console.log firing, but the method was not being called on the server therefore not hitting the db.
Good lesson for me regarding the new recommended file structure. Always import server side code in server/main.js!!! :D
Thanks for your help, thought I was going to go mad!

Build form dynamically in angular2 based on a database driven metadata or json response

​I want to build a form dynamically based on a json response or from a database driven metadata collection/table in Angular 2
Day 1 : There are 3 fields in the json response object.
{
"first_name : "John",
"last_name" : "Doe",
"phone" : "88888888"
}
From this response the form looks like this:
First name: John
Last Name: Doe
Phone: 88888888​
Day 5 : Another field called email is added to the json response which looks like this.
{
"first_name : "john",
"last_name" : "Doe",
"phone" : "88888888",
"email" : "john.doe#angular2.com"
}
Is it possible to show the email field in the browser without making any code change in angular 2.
i.e. therefore no test and deploy cycle.
i.e. dynamically build the form based on some form of database driven metadata or build the form based on the json response object.
The form should look as below:
First name: John
Last Name: Doe
Phone: 88888888​
Email: john.doe#angular2.com​
Is it possible to achieve in Angular 2?
From what I understand, you have a collection of objects. And you want to populate your fields dynamically.
So, an easy way to do that is in the client side, and I'm assuming you are using PHP, you can use something like this:
<div ng-init="yourAngularFunction(<?php $objUsed ?>);">
And in your Angular controller, something like to create a model:
$scope.yourAngularFunction = function(objUsed){
$scope.objUsed = objUsed;
}
And now in your PHP file, you can use, and show all your fields.
First name: {{objUsed.first_name}}
Last Name: {{objUsed.last_name }}
...
And you can also use an angular conditions, like ng-if to show or not the email field.

When to use a nested array versus using a separate collection

I need to use mongoose with dbref but I don't know which design is better for me.
First design:
var user = mongoose.Schema({
name: 'string'
});
var eventSchema = mongoose.Schema({
title: 'string',
propietary_id: 'String',
comments : [{
text: 'string',
user: { type : mongoose.Schema.Types.ObjectId, ref : 'users' },
createdAt: {type: Date, default: Date.now }
}]
});
Second design:
var user = mongoose.Schema({
name: 'string'
});
var eventSchema = mongoose.Schema({
title: 'string',
propietary_id: 'String'
});
var commentSchema = mongoose.Schema({
text: 'string',
event_id : { type : mongoose.Schema.Types.ObjectId, ref : 'events' },
user_id : { type : mongoose.Schema.Types.ObjectId, ref : 'users' },
createdAt: {type: Date, default: Date.now }
});
How it works? On my website there is an event list and if you want to see comments you have to click every event, then angularjs gets all comments (text, user name and user photo) of the selected events.
There are pros and cons with both solutions and the best one for you depends on your usage. Remember that you can produce exactly the same API independent of your design it only comes down to how quickly and easily you can maintain the backend. First some thoughts on both designs:
First design:
First a comment, I wouldn't save comments as a nested document but as an array instead. Otherwise you are limited to one comment per event. Use this schema instead:
comments: [
{
text: { type: String },
user: { type: mongoose.Schema.Types.ObjectId, ref : 'users' },
createdAt: { type: Date, default: Date.now },
}
]
Pros:
No need for multiple collections
You will have the comments returned with the event in the get request which will mean less requests to your backend
No need to map comments to events
Cons:
You will have the comments returned to you with the event, even if you don't want them displayed
If there are a lot of comments to an event, the request response will be pretty large
If you want to remove or edit comments in your array it will be trickier (not impossible though)
Second design:
Pros:
You will have the events and comments separated which means leaner objects
You can much easier extract one comment for edit or delete
You can more easily get events without comments and then request comments at another point
Cons:
You will need to always map comments to events which will mean more code
Two collections will mean two requests usually
Maintenance of another collection
Verdict:
All the pros and cons are judged by how much extra code you need to write. Of course you can always have comments returned with your events in the second design as well but then you will have the extract the comments first and returned them with the event object which will mean extra code to maintain.
I think the second design would work better for you. I'm judging this by your comment that you will only need comments if the user click on an event. I would then be requesting the events first and do another request for comments as soon as the user click on the event, however, having the comments always be returned with the events should make the ui more snappy as the comments will already have been loaded.
It all depends in the end what is more important for you to do with the data. Please let me know if you have any questions on any of the points.

How to generate the right data structure for ngoptions in single request

I'm trying to return a data structure for an Angular screen with several dropdowns.
I don't want to make multiple requests to get the options for each select so I was hoping to create a single nested data structure in Django that contains all the options for each select (there are only a small number)
Angular wants something like this to use with the select and ngoptions directives:
{'booking_name': 'acme',
'current_sales_person': 2,
'sales_people_options': [
{id: 1, name: 'rod'},
{id: 2, name: 'jane'},
{id: 3, name: 'freddy'}
],
... lots more fields here ...
}
sales_people_options would populate the options for the dropdown and current_sales_person indicates which salesperson is initially selected.
How can I get Django Rest Framework to return this in a single request from a ModelSerializer?
I could just create the JSON directly via JSONRenderer but I've got a lot of other fields so I'm keen to use ModelSerializer.
The only way seems to be to add a method called sales_people_options to my Model.
However - I've got several of these fields to generate and it seems very wrong to add model methods for something that I only need for one specific serializer.
EDIT - I think I might need to subclass serializer.Field and override a method (probably field_to_native).
This is just a json object. The Django rest framework is capable of returning json strings which you can then JSON.stringify the string returned to turn it into an object angular is expecting.
{'booking_name': 'acme',
'current_sales_person': 2,
'sales_people_options': [
{id: 1, name: 'rod'},
{id: 2, name: 'jane'},
{id: 3, name: 'freddy'}
Checkout the Django JSON renderer; http://www.django-rest-framework.org/api-guide/renderers
This might be a weird way to do it but it worked:
class BookingSerializer(serializers.ModelSerializer):
class UserOptionsField(serializers.Field):
def field_to_native(self, obj, field_name):
return User.objects.all().values('id', 'username')
sales_people_options = UserOptionsField()
class Meta:
model = Booking
fields = (
'id', 'booking_no', 'current_salesperson', 'sales_people_options',
)
EDIT: And here's a generic solution:
class ModelOptionsField(serializers.Field):
def __init__(self, source=None, label=None, help_text=None, queryset=None, fields=None):
self.queryset = queryset
self.fields = fields
super(ModelOptionsField, self).__init__(source, label, help_text)
def field_to_native(self, obj, field_name):
return self.queryset.values(*self.fields)
that you use like this:
class MySerializer(serializers.ModelSerializer):
my_options_list = ModelOptionsField(queryset=User.objects.all(), fields=('id', 'username'))

MongoDB: Query and retrieve objects inside embedded array?

Let's say I have the following document schema in a collection called 'users':
{
name: 'John',
items: [ {}, {}, {}, ... ]
}
The 'items' array contains objects in the following format:
{
item_id: "1234",
name: "some item"
}
Each user can have multiple items embedded in the 'items' array.
Now, I want to be able to fetch an item by an item_id for a given user.
For example, I want to get the item with id "1234" that belong to the user with name "John".
Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.
I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.
Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.
Thanks for any help or advice you can provide.
The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })
You will have :
{
name: "John",
items:
[
{
item_id: "1234",
name: "some item"
}
]
}
See Documentation of $elemMatch
There are a couple of things to note about this:
1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.
2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.
In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.
3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.
4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.
If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).
If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.
A sample document might look like this:
{
_id: {user_id: ObjectId, item_id: "1234"},
name: "some item"
}
Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).

Resources