Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sails.js Use session param in model

This is an extension of this question.

In my models, every one requires a companyId to be set on creation and every one requires models to be filtered by the same session held companyid.

With sails.js, I have read and understand that session is not available in the model unless I inject it using the controller, however this would require me to code all my controller/actions with something very, very repetitive. Unfortunate.

I like sails.js and want to make the switch, but can anyone describe to me a better way? I'm hoping I have just missed something.

like image 587
Meeker Avatar asked Apr 04 '14 03:04

Meeker


1 Answers

So, if I understand you correctly, you want to avoid lots of code like this in your controllers:

SomeModel.create({companyId: req.session.companyId, ...})
SomeModel.find({companyId: req.session.companyId, ...})

Fair enough. Maybe you're concerned that companyId will be renamed in the future, or need to be further processed. The simplest solution if you're using custom controller actions would be to make class methods for your models that accept the request as an argument:

SomeModel.doCreate(req, ...);
SomeModel.doFind(req, ...);

On the other hand, if you're on v0.10.x and you can use blueprints for some CRUD actions, you will benefit from the ability to override the blueprints with your own code, so that all of your creates and finds automatically use the companyId from the session.

If you're coming from a non-Node background, this might all induce some head-scratching. "Why can't you just make the session available everywhere?" you might ask. "LIKE THEY DO IN PHP!"

The reason is that PHP is stateless--every request that comes in gets essentially a fresh copy of the app, with nothing in memory being shared between requests. This means that any global variables will be valid for the life of a single request only. That wonderful $_SESSION hash is yours and yours alone, and once the request is processed, it disappears.

Contrast this with Node apps, which essentially run in a single process. Any global variables you set would be shared between every request that comes in, and since requests are handled asynchronously, there's no guarantee that one request will finish before another starts. So a scenario like this could easily occur:

  1. Request A comes in.
  2. Sails acquires the session for Request A and stores it in the global $_SESSION object.
  3. Request A calls SomeModel.find(), which calls out to a database asynchronously
  4. While the database does its magic, Request A surrenders its control of the Node thread
  5. Request B comes in.
  6. Sails acquires the session for Request B and stores it in the global $_SESSION object.
  7. Request B surrenders its control of the thread to do some other asynchronous call.
  8. Request A comes back with the result of its database call, and reads something from the $_SESSION object.

You can see the issue here--Request A now has the wrong session data. This is the reason why the session object lives inside the request object, and why it needs to be passed around to any code that wants to use it. Trying too hard to circumvent this will inevitably lead to trouble.

like image 73
sgress454 Avatar answered Oct 10 '22 11:10

sgress454