I am new to meteor and I could not understand that how methods are imported in Meteor. The methods that are starting with
Meteor.methodName,
how to call these methods from client if they are exposed in server.
I have a method called Meteor.loginWithpassword in meteor package livechat / livechat.js.
Its package.js file looks like this:
Package.onUse(function(api) {
api.versionsFrom('1.0');
api.addFiles('livechat.js', 'server');
}
Now I want to call Method loginWithPassword method from client.How to achieve this??
Related
Meteor has special directories: server and client for serving files only to server or only to client.
Is it possible to make similar behaviour, but using not client and server folder names but file names which end with either .client.js or .server.js?
For example collections.client.js would be available only on client and collections.server.js would be available only on server?
UPD
Maybe it is possible to create smart package which will take control of files serving?
This is not possible, what you can do however, is the following :
lib/collections/collection.js
Declare the collection and common client/server behavior such as Meteor.methods.
client/collections/collection.js
Declare client specific helpers regarding the collection.
server/collections/collection.js
Declare publications and other server-side helpers.
You could alternatively declare everything in lib/collections/collection.js and use Meteor.isClient and Meteor.isServer blocks.
This might be OK for very small files but it can quickly become a mess for larger projects.
I'm not sure if the Meteor build tool is smart enough to strip Meteor.isServer from the bundle served to the client.
You can also use a modular approach and use packages instead, with the Package API you can control precisely the context where a file is supposed to be executed.
Package.describe({
name: "my-app-module",
description: "Handles some feature in My App",
version: "1.0.0"
});
Package.onUse(function(api){
api.addFiles({
"my-module/shared.js"
},["client","server"]);
//
api.addFiles({
"my-module/client.js"
},"client");
//
api.addFiles({
"my-module/server.js"
},"server");
//
api.export("MyModule",["client","server"]);
});
Hmmm, for now you can't do this, but you can put your code in
if (Meteor.isServer) {
// your server code
};
if (Meteor.isClient) {
// your client code
};
I am using the sanjo:jasmine and velocity:html-reporter packages in my app to try and implement some unit and integration testing. Using this tutorial as a guide, I have a few unit tests and a couple integration tests done. What I am not able to figure out is how to get code to run in the "test" environment that is not part of a unit test or integration test, but needs to run prior to the tests and only for the tests.
What I am trying to solve is that I need some dummy users created for testing, but I do not want them in my production app. Sort of like an "init" phase where you can build the mockups and insert any data you need. Is there a way to accomplish this?
I would recommend that you create some seed or fake data for your tests using factories.
I would recommend that you try the following packages:
anti:fake - Fake text and data generator for Meteor.js
dburles:factory - A package for creating test data or for generating fixtures.
You can install these packages using this command:
meteor add anti:fake dburles:factory
Create your factory data for the test environment only.
I'd create a file called server/seeds.js with the following content:
Meteor.startup(function() {
Factory.define('user', Users, {
username: "test-user",
name: "Test user",
email: "test#example.com"
// add any other fields you need
});
var numberOfUsers = 10;
// Ensure this is the test environment
if (process.env.NODE_ENV === 'test') {
// Create the users from the factory definition
_(numberOfUsers).times(function(n) {
Factory.create('user');
});
}
});
You can follow this Factory approach for any data, not just Users.
If your Users need to login, such as when you're using accounts:base, then I would consider an alternative approach to using Factory data:
var email = "test#example.com";
var password = "secret";
var name = "Test user";
Accounts.createUser({email: email, password: password, profile: {name: name}});
Please see Accounts.createUser in the Meteor docs for more details.
If you're using sanjo:jasmine you can insert data into the mirrored db before writing your specs (after describe and before it clauses) and this data would be available for all specs.
Also, you may use beforeEach() in order to provide data for each specs, and then you can delete it using afterEach().
Here you can find more info.
I've been using mike:mocha and as long as your specs are written inside a folder called tests (and then client / server, respectively) then Velocity puts data in velocity specific collections. I run the same Meteor method I use to insert a document in my main app, but velocity knows to put it in the mirrored version.
We can define methods on Meteor server and call them from clients, is there any way to call client defined methods from server?
As per official Docs there is no direct way to call client side methods from server but you can achieve that by using a smart package called anti:methods
You need to set the clientId which will be used to communicate to this particular client.
Tracker.autorun(function() {
Meteor.ClientCall.setClientId(Meteor.userId());
});
Defining a method
Meteor.ClientCall.methods({
'chatMessage': function(username, message) {
...
},
});
Calling a method
Meteor.ClientCall.apply(clientId, method, arguments, callback)
Note: This package is not fully functional. Check the readme for more information.
Alternatively if you just want to re-use some code in both server and client, you can create a global function in common folder and call it from anywhere you want. Just make sure it does not contain any browser specific code and it loads before the function where you calling it.
I am using SignalR to build Real time application
I have added the following code to application start in the global.asax file
'Register the default hubs route: ~/signalr
RouteTable.Routes.MapHubs()
and I got the following error:
A route named 'signalr.hubs' is already in the route collection. Route names must be unique.
Parameter name: name
It's most likely you are calling this twice. Check all your code that this is not the case, including any App_Start code. Do a global search within your app for "MapHubs".
Also check you have only one version of Signal installed (older versions had a different namespace).
This screencast shows how to retrieve additional user profile attributes from external authentication. But I don't understand how can I update the user account every time user logs in with possibly updated profile attributes? Is onCreateUser called every time user authenticates or just the first time? From what I understand it is just the first time. So how can I hook into login process to update attributes?
You need to hook into when someone logs in and then update the attributes manually.
Firstly you need something that tells when the user is logged in. At the moment you could use a client based solution (where a call is made to the server a second time on a successful login) using something like meteor-prescence or by editing the core packages and placing them in your /packages directory.
Alter the accounts-base package with the file accounts-server.js to create a 'hook' when the user logs in at
Meteor.methods({
login: function(options) {
.....
if (result !== null)
//Run here
this.setUserId(result.id);
return result;
},
});
Then at the //Run Here add a function that connects to facebook and gets the data you need. Or in the Meteor.call method that you would call from the client if you decide to use meteor-prescence or a similar library or method. It would be something similar to this:
if(Meteor.user().services.facebook.accessToken) {
var graph = Npm.require('fbgraph');
graph.setAccessToken(Meteor.user().services.facebook.accessToken);
graph.get('/me',{},function(err,result) {
//Update your user (you could also alter services.facebook instead
Meteor.users.update(Meteor.userId, {$set: {profile:result}});
}
}
In the above the example is for facebook using the fbgraph node module (which you would need to install) - or use the method described here to use Npm modules without a seperate package. You could to the same in principle for other providers too. Note you don't have to use a synchronous type call here to your provider as it is ok the data could be updated shortly after they log in.
Another place you could hook into is also in the _setUserId method in the livedata package.