Meteor Routing and subsequent data order - mongodb

I got stuck at understanding Meteor Routes and data flow.
In the beginning it was simple blog app, with 1 collection named Posts.
Now I want to store history of changes, so I've created a second collection and named it History.
On every edit in Posts I'm adding state of post (author,content, etc ...) to History including the ID of edited post.
Question is how should I configure Iron Router to make it pass the current post id to posts/:_id/history from previous state (posts/:_id/) and get entries from History with this matching ID?

To pass the id from one view to the next, you can do it via template like so:
<a href="/posts/1/history>Post History</a>
or
<a href="/posts/{{_id}}/history>Post History</a>
or programmatically like so:
Router.go('postHistory', {_id: 1});
To get the history entries, you can resolve the data in iron router during the route request as so:
this.route('postHistory', {
path: '/posts/:_id/history',
data: function() {
return History.findOne({postId: this.params._id});
}
});

Without seeing your code it is hard to tell what you have tried already. But in order to help you understand Meteor routes perhaps you could take a look at these two links:
This introduction to routes with Iron Router
This link on more advanced routes
These should help you comprehend how to make two collections work together.

Related

Mongo conditional find

So I have this article page and I need to place related articles below the current article body.
There are certain attributes that I use to find similar articles but in case there isn't any, or if there is less than 2 found, I need to add just some other articles to the result.
So if a given article has a tag "Development", I need to search for 2 other articles with that tag, and if there is less than 2 that have this tag, I need to pull just some other articles.
Right now the flow is:
I make a request to get an article using query
I make request for related articles using the result of the first request.
But now I have difficulty understand how to make another request or put a condition into the second request to optimally get another article(s).
I appreciate any help
const article =await "your collection". find({tag:"Development"}).limit(2);
const x=2 - article.length
while(x>0){
var y=await "your collection". findOne();
article.push(y);
x--;
}

find and limit array values in an array from a document

I can explain my issue using facebook as example,
take one news feed(one post), which has
post-content,images,videos
likes,comments,share
I'm saving the post_content,images,video(urls only) and like count in one collection called post
and all the likes in another collection called post_likes
now in the timeline I'm getting top 10 posts from the db
Posts.find({},{sort: {createdAt: -1}}.limit(10)
now, whenever user clicks on like, I'm calling a method which inserts the userid into the collection
post_likes.update({post_id:id},{$push:{userids: this.userId}})
post_likes object
{_id:"xxxx",post_id:"Id of the post",userids:["xxx","yyy",....]
I'm displaying in my template using
{{#each posts}}
.............
.........
........
.......
{{#if likes}}
//show dislike button
{{else}}
//show like button
{{/if}}
{{/each}}
Here my issue is
I want to know that current user is liked particular post or not.
I can't load all the liked_users to client side and check.
So I want to publish only one value from array to client
How to do this?
or Is there any alternatives to do this, any idea is welcome and appreaciated.
There are several alternatives:
Publish post_likes for each user:
Meteor.publish('user_post_likes', function() {
return post_likes.find({userids: this.userId});
});
Attach the post id to the user doc as well as vice versa:
post_likes.update({post_id:id},{$push:{userids: this.userId}}); // AND
Meteor.users.update({_id: this.userId}, {$push: {'profile.post_likes': id}});
Then you will have the likes already present in the user doc to which Meteor automatically subscribes. You can use something like matb33:collection-hooks to keep the two collections in sync if required.
Write a method to retrieve liked posts on demand:
Meteor.methods({
get_liked_posts: function() {
return post_likes.find({userids: this.userId});
}
});
The third is less "meteoric", but may be preferable if having lots of users subscribe to their own posts_likes subscriptions independently is hard work for the server. However, in that event, option 2 might be preferable instead.

Symfony2 Form Rest Api only add to Relation

I am using Symfony2 as Rest Api for a JS Frontend App. I came across a scenario where I want users to "invite" (=add) Users to a Group. But I want to only allow them to add Users to the existing Relation and not "overwrite" the whole relation, which is the standard behaviour in combination with a regular Symfony2 Form.
What would be the best practice to achieve this behaviour?
Additional Comment:
I am using Ember-Data in the frontend and my frontend would probably send a put request with the whole Group including additional users (but not all).
My JSON Payload would look something like this:
{
"usergroup": {
"name":"yxcv2",
"stake":"sdfghj",
"imageName":null,
"userCount":5,
"users":[
5,
6,
7
],
"gameGroup":"13",
}
}
In this scenario User 1,2,3 and 4 are already members of the group. And instead of replacing 1,2,3,4 with 5,6,7, I want to ADD 5,6,7 to the already existing members.
A LINK request should be used to add an item to an existing collection instead of overwriting it with a POST request.
Using a symfony form you'd post the User (id) plus a hidden field _method with value LINK to something like /groups/{id}.
routing would be something like this:
group_invite:
path: /groups/{id}
defaults: { _controller: YourBundle:Group:inviteUser }
methods: [LINK]
You could use FOSRestBundle's implicit resource name definition, too.
For the method override to work the config setting framework.http_method_override needs to be set to true ( = default value - available since symfony version 2.3).
More information can be found in the documentation chapter:
How to use HTTP Methods beyond GET and POST in Routes

Sail.js - routing to methods, custom policies & PATCH method

I have a few questions that I couldn't find answers anywhere online.
Does sails.js framework support HTTP PATCH method? If not - does anyone know if there is a planned feature in the future?
By default if I create method in a controller it is accessible with GET request is it the routes.js file where I need to specify that method is accessible only via POST or other type of methods?
How would you create a policy that would allow to change protected fields on entity only for specific rights having users. I.e: user that created entity can change "name", "description" fields but would not be able to change "comments" array unless user is ADMIN?
How would you add a custom header to "find" method which specifies how many items there are in database? I.e.: I have /api/posts/ and I do query for finding specific items {skip: 20; limit: 20} I would like to get response with those items and total count of items that would match query without SKIP and LIMIT modifiers. One thing that comes to my mind is that a policy that adds that that custom header would be a good choice but maybe there is a better one.
Is there any way to write a middle-ware that would be executed just before sending response to the client. I.e.: I just want to filter output JSON not to containt some values or add my own without touching the controller method.
Thank you in advance
I can help with 2 and 5. In my own experience, here is what I have done:
2) I usually just check req.method in the controller. If it's not a method I want to support, I respond with a 404 page. For example:
module.exports = {
myAction: function(req, res){
if (req.method != 'POST')
return res.notFound();
// Desired controller action logic here
}
}
5) I create services in api/services when I want to do this. You define functions in a service that accept callbacks as arguments so that you can then send your response from the controller after the service function finishes executing. You can access any service by the name of the file. For example, if I had MyService.js in api/services, and I needed it to work with the request body, I would add a function to it like this:
exports.myServiceFunction = function(requestBody, callback){
// Work with the request body and data access here to create
// data to give back to the controller
callback(data);
};
Then, I can use this service from the controller like so:
module.exports = {
myAction: function(req, res){
MyService.myServiceFunction(req.body, function(data){
res.json(data);
});
}
}
In your case, the data that the service sends back to the controller through the callback would be the filtered JSON.
I'm sorry I can't answer your other questions, but I hope this helps a bit. I'm still new to Sails.js and am constantly learning new things, so others might have better suggestions. Still, I hope I have answered two of your questions.

Angular JS: Full example of GET/POST/DELETE/PUT client for a REST/CRUD backend?

I've implemented a REST/CRUD backend by following this article as an example: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/ . I have MongoDB running locally, I'm not using MongoLabs.
I've followed the Google tutorial that uses ngResource and a Factory pattern and I have query (GET all items), get an item (GET), create an item (POST), and delete an item (DELETE) working. I'm having difficulty implementing PUT the way the backend API wants it -- a PUT to a URL that includes the id (.../foo/) and also includes the updated data.
I have this bit of code to define my services:
angular.module('realmenServices', ['ngResource']).
factory('RealMen', function($resource){
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT'},
remove: {method:'DELETE'}
});
I call the method from this controller code:
$scope.change = function() {
RealMen.update({entryId: $scope.entryId}, function() {
$location.path('/');
});
}
but when I call the update function, the URL does not include the ID value: it's only "/realmen", not "/realmen/ID".
I've tried various solutions involving adding a "RealMen.prototype.update", but still cannot get the entryId to show up on the URL. (It also looks like I'll have to build the JSON holding just the DB field values myself -- the POST operation does it for me automatically when creating a new entry, but there doesn't seem to be a data structure that only contains the field values when I'm viewing/editing a single entry).
Is there an example client app that uses all four verbs in the expected RESTful way?
I've also seen references to Restangular and another solution that overrides $save so that it can issue either a POST or PUT (http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/). This technology seems to be changing so rapidly that there doesn't seem to be a good reference solution that folks can use as an example.
I'm the creator of Restangular.
You can take a look at this CRUD example to see how you can PUT/POST/GET elements without all that URL configuration and $resource configuration that you need to do. Besides it, you can then use nested resources without any configuration :).
Check out this plunkr example:
http://plnkr.co/edit/d6yDka?p=preview
You could also see the README and check the documentation here https://github.com/mgonto/restangular
If you need some feature that's not there, just create an issue. I usually add features asked within a week, as I also use this library for all my AngularJS projects :)
Hope it helps!
Because your update uses PUT method, {entryId: $scope.entryId} is considered as data, to tell angular generate from the PUT data, you need to add params: {entryId: '#entryId'} when you define your update, which means
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT', params: {entryId: '#entryId'}},
remove: {method:'DELETE'}
});
Fix: Was missing a closing curly brace on the update line.
You can implement this way
$resource('http://localhost\\:3000/realmen/:entryId', {entryId: '#entryId'}, {
UPDATE: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId' },
ACTION: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId/action' }
})
RealMen.query() //GET /realmen/
RealMen.save({entryId: 1},{post data}) // POST /realmen/1
RealMen.delete({entryId: 1}) //DELETE /realmen/1
//any optional method
RealMen.UPDATE({entryId:1}, {post data}) // PUT /realmen/1
//query string
RealMen.query({name:'john'}) //GET /realmen?name=john
Documentation:
https://docs.angularjs.org/api/ngResource/service/$resource
Hope it helps