I have a setup route in which the first user creates his account. If he already has an account he has to be redirected to the index route.
On the serverside i would do it like this:
if(Meteor.users.find().count > 0){
//do stuff
}
The users collection isn't published to the client. How can i return a simple true/false from the server to a route definition? I tried with Meteor.call('hasUser' function(result){
console.log(result);
});
But since call is async on the client i always get 'undefined' in my result
This has already been asked and answered here, however you could also do this with the publish-counts package:
$ meteor add tmeasday:publish-counts
server
Meteor.publish('userCount', function() {
Counts.publish(this, 'userCount', Meteor.users.find());
});
client
Meteor.subscribe('userCount');
...
Counts.get('userCount');
In addition, it also comes with helpers like:
<p>There are {{getPublishedCount 'userCount'}} users</p>
Related
I'm working on a medium-sized website and I figured that I need to write more maintainable code with better project structure.
I found this article and a few others describing basically the same idea about 3-layer architecture
I find it great as I wasn't using the service layer before and It helped to DRY the code
but the article doesn't include anything about validation and how it should be handled. especially when validation is done against database (like checking resource existence)
Should I do the validation in the service layer or write validation middleware (which will need to access database and I think this is against the pattern described)
for example, I ended up with two API endpoints where website users update and remove their already added DeliveryAdddress. As you can see below validation in the service layer led to routes having duplicated code to handling HTTP response.
my routes files
router.put('/delivery-addresse/:id', DeliveryAddressesController.update);
router.delete('/delivery-addresses/:id', DeliveryAddressesController.remove);
DeliveryAddressesController
async update(req, res){
try {
....
await AddressesService.updateDeliveryAddress(userId, address);
....
} catch(error){
if (error instanceof ValidationError){
if (error.name === 'NO_SUCH_ADDRESS'){
return res.status(404).json(error);
}
}
....
}
},
async remove(req, res){
try {
...
await AddressesService.removeDeliveryAddress(userId, addressId);
....
} catch(error){
if (error instanceof ValidationError){
if (error.name === 'NO_SUCH_ADDRESS'){
return res.status(404).json(error);
}
}
....
}
},
Options
I could think of these options but not sure if they're good and which one.
Validation middleware before the controller which (the middleware) itself will call the
validation method in the service.
I think it's a good option but, maybe I
will end up with multiple database calls to fetch the resource if I don't store the result
in the req object
Using a function in the catch block to check for any ValidationErrors and respond but it's not a great readable way.
The first question you need to ask is what credentials I should write for ... The middleware layer is between the two layers of operation and application, and it is very important what kind of validation you want to do ... For example, if you want two communication services on a network, Establish a key for it and you need a validator to check every key in each service. In this case, it is better to send this key in the header and validate it in middleware, but sometimes you want to evaluate information from other services or even from the database, which requires several validation steps. It is better to implement them all in your services layer! I suggest option 2 for this 😉
The title might sound strange, but I have a website that will query some data in a Mongo collection. However, there is no user system (no logins, etc). Everyone is an anonymouse user.
The issue is that I need to query some data on the Mongo collection based on the input text boxes the user gives. Hence I cannot use this.userId to insert a row of specifications, and the server end reads this specifications, and sends the data to the client.
Hence:
// Code ran at the server
if (Meteor.isServer)
{
Meteor.publish("comments", function ()
{
return comments.find();
});
}
// Code ran at the client
if (Meteor.isClient)
{
Template.body.helpers
(
{
comments: function ()
{
return comments.find()
// Add code to try to parse out the data that we don't want here
}
}
);
}
It seems possible that at the user end I filter some data based on some user input. However, it seems that if I use return comments.find() the server will be sending a lot of data to the client, then the client would take the job of cleaning the data.
By a lot of data, there shouldn't be much (10,000 rows), but let's assume that there are a million rows, what should I do?
I'm very new to MeteorJS, just completed the tutorial, any advice is appreciated!
My advice is to read the docs, in particular the section on Publish and Subscribe.
By changing the signature of your publish function above to one that takes an argument, you can filter the collection on the server, and limiting the data transferred to what is required.
Meteor.publish("comments", function (postId)
{
return comments.find({post_id: postId});
});
Then on the client you will need a subscribe call that passes a value for the argument.
Meteor.subscribe("comments", postId)
Ensure you have removed the autopublish package, or it will ignore this filtering.
For example, if I did a chatroom where all you ahve to do is enter a username (so you don't log in), can I still somehow list out all the people in that chatroom? How can I do this?
Instead of using the normal Meteor.users collection, it would probably be easiest to create your own collection for such simple authentication.
If you wanted to make it really simple (most likely, as long as you didn't care if 2 people have the same name), just store the name as a property of a chat room message document.
Edit - answer to comment:
To detect when a user disconnects, you can add an event handler in your publish function like this:
Meteor.publish('some_collection', function(){
var connectionId = this.connection ? this.connection.id : 'server';
this._session.socket.on("close", Meteor.bindEnvironment(function(){
// deal with connectionId closing
}));
});
You can do that.
Simply publish all users and every coming client should subscribe.
server:
Meteor.publish('allUsers', function(){
return Meteor.users.find({},{fields:{profile:1}});
})
client :
Meteor.startup(function(){
Meteor.subscribe('allUsers');
})
Template.listOfUsers.users = function(){
return Meteor.users.find();
}
This is very basic example, which should be adjusted to your needs.
In my meteor app I have a couple of publish/subscribe setup. Now I need to have an other for all users in the system. Now I don't need this information all the time, only when the user opens the configuration overlay. What is the preferred way to load the data on a specific user action (click on a button for example).
I'm also wondering about pagination, in case the number of users is huge, is something like this possible ?
You can always use Meteor.call()
http://docs.meteor.com/#meteor_call
You declare Meteor.call on the client and the method on the server. You can return any data you want,
// client
Meteor.call('getData', function(error, data) {
// do something with data
})
// server
Meteor.methods({
getData: function() {
// return some data
}
});
For pagination, look into using the Reactive Tables package on Atmosphere / Meteorite.
Sorry for the bad phrasing.
Essentially, I want to be able to generate a link to a page, which will load a session of certain docs.
For example, Links.find() returns to Client A Links.find({clientName:"A"}). Now Client A wants to send this series of elements to his friend, and wants to do so by sending him a link which loads a client instance that can see Links.find({clientName"A"}).
Any input at all would be greatly appreciated.
Add Iron Router to your project. Then create a route that puts the relevant query into the URL, for example (in a client-loaded JavaScript file):
Router.map(function () {
this.route('client', {
path: '/client/:_clientName',
before: function () {
this.subscribe('client', this.params._clientName).wait();
}
}
}
Then a URI like http://yourapp.com/client/A would cause the client template to render (by default it uses the same name as the route name, unless you specify a different name) subscribing to the client subscription using "A" as the subscription parameter. This would be paired on the server side with:
Meteor.publish('client', function (clientName) {
// Clients is a Meteor collection
return Clients.find({clientName: clientName});
});
So that's how to process links after they've been generated. As for creating them, just work backwards: what query parameters are you passing to your subscription (that in turn get put into the find() call to MongoDB)? Identify each of them and write some code that adds them to an appropriate URI—in this case, your function would simply concatenate "http://yourapp.com/client/" with clientName, in this case "A". Obviously much-more-complicated routes/URIs and queries are possible, for example http://yourapp.com/events/2012-01-01/2012-12-31 with an Iron Router route path of /events/:_fromDate/:_toDate and so on.