Why do Meteor methods go in the models.js file? - meteor

According to this video, meteor methods should be defined in the models.js file that is available on the client and the server.
If methods are supposed to be secure procedures that the client invokes on the server, why are they defined in the models.js file? Clients call methods with Meteor.call, so doesn't it make sense to define our methods on the server, not in models.js?

You don't have to put methods in a "model.js" file, you can put them anywhere, they just happened to name the file model.js in the video.
Meteor.methods is an "Anywhere" method, which means that it can exist on both the server and the client. If you look at the docs, you'll see the difference explained:
Calling methods on the server defines functions that can be called remotely by clients.
[...]
Calling methods on the client defines stub functions associated with server methods of the same name.
In the video they're showing you a demo of how methods and other features of Meteor work, so they weren't concerned with specifically placing the methods in the server.

The video you posted is merely a teaser of what Meteor can do. It's not a tutorial. The documentation explains how methods do work. For clients the method will only be stubbed.
If you make the method available at the server only, the method won't be stubbed. You should also read the concepts of Meteor.

Related

How to access dependency injection container in Symfony 4 without actual injection?

I've got a project written in Symfony 4 (can update to the latest version if needed). In it I have a situation similar to this:
There is a controller which sends requests to an external system. It goes through records in the DB and sends a request for every row. To do that there is an MagicApiConnector class which connects to the external system, and for every request there is a XxxRequest class (like FooRequest, BarRequest, etc).
So, something like this general:
foreach ( $allRows as $row ) {
$request = new FooRequest($row['a'], $row['b']);
$connector->send($request);
}
Now in order to do all the parameter filling magic, the requests need to access a service which is defined in Symfony's DI. The controller itself neither knows nor cares about this service, but the requests need it.
How can my request classes access this service? I don't want to set it as a dependency of the controller - I could, but it kinda seems awkward, as the controller really doesn't care about it and would only pass it through. It's an implementation detail of the request, and I feel like it shouldn't burden the users of the request with this boilerplate requirement.
Then again, sometimes you need to make a sacrifice in the name of the greater good, so perhaps this is one of those cases? It feels like I'm "going against the grain" and haven't grasped some ideological concept.
Added: OK, the full gory details, no simplification.
This all is happening in the context of two homebrew systems. Let's call them OldApp and NewApp. Both are APIs and NewApp is calling into the OldApp. The APIs are simple REST/JSON style. OldApp is not built on Symfony (mostly even doesn't use a framework), the NewApp is. My question is about NewApp.
The authentication for OldApp APIs comes in three different flavors and might get more in the future if needed (it's not yet dead!) Different API calls use different authentication methods; sometimes even the same API call can be used with different methods (depending on who is calling it). All these authentication methods are also homebrew. One uses POST fields, another uses custom HTTP headers, don't remember about the third.
Now, NewApp is being called by an Android app which is distributed to many users. Android app actually uses both NewApp and OldApp. When it calls NewApp it passes along extra HTTP headers with authentication data for OldApp (method 1). Thus NewApp can impersonate the Android app user for OldApp. In addition, NewApp also needs to use a special command of OldApp that users themselves cannot call (a question of privilege). Therefore it uses a different authentication mechanism (method 2) for that command. The parameters for that command are stored in local configuration (environment variables).
Before me, a colleague had created the scheme of a APIConnector and APICommand where you get the connector as a dependency and create command instances as needed. The connector actually performs the HTTP request; the commands tell it what POST fields and what headers to send. I wish to keep this scheme.
But now how do the different authentication mechanisms fit into this? Each command should be able to pass what it needs to the connector; and the mechanisms should be reusable for multiple commands. But one needs access to the incoming request, the other needs access to configuration parameters. And neither is instantiated through DI. How to do this elegantly?
This sounds like a job for factories.
function action(MyRequestFactory $requestFactory)
{
foreach ( $allRows as $row ) {
$request = $requestFactory->createFoo($row['a'], $row['b']);
$connector->send($request);
}
The factory itself as a service and injected into the controller as part of the normal Symfony design. Whatever additional services that are needed will be injected into the factory. The factory in turn can provide whatever services the individual requests might happen to need as it creates the request.

Meteor: optimistic ui and appCache

How does a meteor application deal with server-side methods for inserting and updating? especially:
if an application is temporarily offline (available through appCache-package) and a call to a server-side
method happens: is optimistic-ui possible? how does it work?
do i
need to define the (usually server-side) methods in /libs
directory instead of /server?
Thank you
You should put your collections under libs and use Collection.allowand Collection.deny to control the permission on both server and client side.
In meteor, most of the time you're dealing with client side data, Meteor will save them to the Minimongo and synchronize your update to server when available.
Regarding to method definition, it really depends on where you want to use it, only a few things you'll put on server, e,g, authentication logic, encryption salt

Meteor: are code inside Meteor.isServer block readable from client?

I am confused as to when you would use the isServer block to put stuff in. obviously, database calls and etc. Does this show up in the client browser?
I would advise against using that instead put your stuff in folders as advised on the unofficial meteor faq
Even if you use if (Meteor.isServer) {...} this block will still be sent down to the client if you don't use the folder structure above i.e putting it in /server. But it will ignore all the code inside it.
On the server side code you would place code you only want to run on the server, i.e Publish functions, and data that would be more sensitive & the user shouldn't have access to.
I think it does get sent down to the client, unless it's in the server folder. In response to one of the comments about sharing global variables, I've been using this pattern. Create the same global variable in client and server folders respectively, and once outside of those folders for any shared code. Initialize the global variable in each place by testing to see if it already exists.
MyVar = typeof MyVar === 'undefined' ? {} : MyVar;
Then, just put methods where you need them. For instance, I'll have a User object with a method that tests to see if the user is authorized. I'll declare the method once on the server global User, and once on the client global User. The methods are different because the server version checks for custom properties on the user object which aren't available on the client. Then, in a Meteor.methods method, which runs on both the client and server, you can invoke the authorization method, and it will call different methods depending on if it's running on the client or server.
I was asking myself the same question today and stumbled upon this package:
https://github.com/mquandalle/meteor-minifiers
It seems like Meteor does not remove the Meteor.isServer Blocks by default.
See this discussion:
https://groups.google.com/forum/#!topic/meteor-talk/iHat47f6iGE
I haven't used it as of now, but it looks promising.
If you do not want to use an extra package, I'd recommend to use the client and server folders. Only the files in the client folder are sent to the client.

node.js asynchronous initialization issue

I am creating a node.js module which communicates with a program through XML-RPC. The API for this program changed recently after a certain version. For this reason, when a client is created (createClient) I want to ask the program its version (through XML-RPC) and base my API definitions on that.
The problem with this is that, because I do the above asynchronously, there exists a possibility that the work has not finished before the client is actually used. In other words:
var client = program.createClient();
client.doSomething();
doSomething() will fail because the API definitions have not been set, I imagine because HTTP XML-RPC response has not returned from the program.
What are some ways to remedy this? I want to be able to have a variable named client and work with that, as later I will be calling methods on it to get information (which will be returned via a callback).
Set it up this way:
program.createClient(function (client) {
client.doSomething()
})
Any time there is IO, it must be async. Another approach to this would be with a promise/future/coroutine type thing, but imo, just learning to love the callback is best :)

In flex how do I pass data retrieved from a remote object service to a modules interface?

I found at this Adobe tutorial a nice "RemoteService" class that creates a RemoteObject and contains the functions for handling the result and fault events. If I wanted to use this approach, how could I pass the data from the result handler to interfaces that modules from the main application could use?
I could put the RemoteService/RemoteObject in the modules, but (in my opinion- and I could be wrong) the best design seems to be using the remote calls in the main app and passing the data along to the modules.
I think you're correct -- have the remote calls in the main app if other parts of the app will need the data.
To get data into the module, just set a property of the module to the data. So a result handler in the main app sets myModule.someObject = event.result.someObject.
To get data from the module back to the app, dispatch an event. This way the module is loosely coupled to whoever its host is.

Resources