Class and scope in ember js - javascript

Im building an ember application consuming a couple of web services. And I'm trying to pass a class object throw the config/environment file doing this:
var myclass = require('myclass-package');
var ENV = {
APP: {
MY_OBJ_CLASS: new myclass({
//CONSTRUCTOR PARAMS...
PROP1: "HELLO"
})
}
}
In my ember app/controllers I'm doing this:
import ENV from '../config/environment';
var obj1 = ENV.APP.MY_OBJ_CLASS;
I can see that the object is instantiated if I console.log the class object but when I try to access to the properties and functions, I can't and I get back this error:
var data = obj1.my_function_class({param1:1});
console.log(data)
TypeError: obj1.my_function_class is not a function
But the function exist...
What is the way to access to my class properties and functions?

config/environment.js is a special file. It is executed in Node, then serialized to be made available for the browser app.
You should not store any functionality in that file.
Put your class into a proper Ember module. Depending on what you're trying to achieve, that could be a service, a model, an util, etc.
Provide more details on your original problem, not your attempted solution. See http://xyproblem.info .

Related

Api class that can Initialize dynamic modules and unite them under its hood

I am trying to figure out a pattern where a single class can instantiate dynamic module classes and attach them to itself.
For example, I have
Module 1
class object1 {
construct(params) {
this.params = params
}
}
module.exports = object1
Module 2
class object2 {
construct(params) {
this.params = params
}
}
module.exports = object2
And an API module that would somehow instantiate an unlimited amount of objects and sort of attach them to itself.
class Api {
}
module.exports = new Api;
The functionality of API module should work like so let obj = api.object1('param1').object2('param2') // { object1: {params: 'param1'}, object2: {params: 'param2'}}
I can manually set all methods in the api class but that's not the solution I look for. I want to be able to initialize all modules and dynamically attach them onto the api class, pass all the arguments to modules and generate object in the output that sort of reflects the example above.
Is it achievable at all? Or maybe someone recognizes this pattern and know whats it called so that I could research it further? I tried achieving this using Proxy but was unsuccessful.

How to access the .setup function on a feather-sequelize object?

I want to nest a service behind another one, just as described in the FAQ and this issue
As I understood, you need the .setup property to get access to the app object, on which you can add a listener that you link to your service. So far so good.
However, the service I would need to do that on is not a custom service, on which the setup property is readily available, but a feathers-sequelize service, which seems to be built else where, the .class.js is not even present.
Searching around, I ve seen you can still access the property with the protoype, but not I am reticent in modifying it without knowing it to be something supported.
TL:DR: How to nest a feather-sequelize service behind another one?
You can extend the existing Sequelize ES6 class as documented here:
const { Service } = require( 'feathers-sequelize');
class MyService extends Service {
setup(app, path) {
this.app = app;
// Do stuff here
}
}
app.use('/todos', new MyService({
paginate: {
default: 2,
max: 4
}
}));

new object in constructor from class undefined

I'm creating a new object from a class in a constructor, and whenever it runs I get an error that operate is undefined in the method, though it is defined in the constructor. Operate itself is thoroughly tested and works great in a separate context so that's not the problem. I'm building it with Babel, not running it directly in Node 7.0.0
import Operate from "./operate"
export default class {
constructor(Schema) {
this.schema = Schema
this.operate = new Operate(this.schema)
console.log(this.operate.run) // <- Logs just fine
}
update(req, res) {
console.log(this.operate.run) // <- Nada
this.operate.run(req.body)
.then(value => {
res.status(200).json(value)
})
}
This feels like I'm missing something fundamental. I've heard this isn't a great pattern anyway, so please feel free to suggest a better way. Thanks so much in advance.
UPDATE: This is how update is being used. I don't suspect there's any problem here, as it has worked just fine when I had been importing controller as a function from another module, instead of a class
import {Router, } from "express"
import Controller from "../controller"
import User from "./user.model"
let controller = new Controller(User)
let router = new Router()
router.post("/", controller.update)
module.exports = router
Change from this:
router.post("/", controller.update)
to this:
router.post("/", controller.update.bind(controller))
When you pass controller.update it only passed a pointer to the method and any association with the controller object is lost. Then, when that update method is called later, there is no association with the appropriate object and thus the this handler in the method is wrong and you get the error you were seeing.
You either force the binding of the update method within the object or when you pass the method elsewhere that might not be called correctly, you can use the above structure to pass a bound version of the method.
You could also modify your definition of the update method to permanently bind it to your object in the constructor by adding this to the constructor:
this.update = this.update.bind(this);

In a Node app with express JS, how can I include and run a separate JS file?

I have a javascript file that contains some functions that grab an RSS feed and save the contents in a database. I originally had it being called by the HTML page, but I want this file to instead be running in the back-end all the time (grabbing updates from the RSS feed and saving it to a database).
My question is, how can I attach and run this separate javascript within my app? I assume it will look like this:
In app.js:
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.SomeFunction();
This isn't working though. Also, would variables declared in my app.js be available in RSSReader.js?
Thanks.
how can I attach and run this separate javascript within my app?
The app.js code you show should work just fine. The key is that you have to make your RSSReader.js file into a module that exports the functions it wants to be public:
So, inside of RSSReader.js, you would have something like this:
module.exports = {
someFunction: function() {
// code here
},
someOtherFunction: function() {
// code here
}
};
Then, in your other file, you can load that module and use it like you had:
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.someFunction();
RssReader.someOtherFunction();
node.js documentation for modules is here.
Also, would variables declared in my app.js be available in
RSSReader.js?
No, they would not unless you explicitly declared the app.js variables as properties on the global object. The usual node.js convention for sharing from app.js to another module is that you create an initializer method for the RSSReader.js module (you can call it init) and you pass it any context it needs (usually an object with some properties on it) from app.js and the RSSReader.js module can then store that context for its use.
So, if you want to share some variables from app.js to RSSReader.js, you could share them via a .init() method like this:
RSSReader.js
var data;
module.exports = {
init: function(options) {
data = options;
},
someFunction: function() {
// code here can access the data variable
},
someOtherFunction: function() {
// code here can access the data variable
}
};
app.js
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.init({express: express, db: db});
RSSReader.someFunction();
RssReader.someOtherFunction();

In Ember.js, how do you hook an object into a generic application namespace

Let's say I declared an application namespace:
App = Ember.Application.create();
and later I write an arrayController instance that creates objects and hook it onto the app namespace on user event:
App.objController = Ember.ArrayController.create({
content: [],
createObj: function(){
// instantiate new object
var newObj = Ember.Object.create({ ... })
//give obj a name
var newObjName = this._getObjName( someParam );
// hook object to an app namespace -> this is where I have an issue
App[newObjName] = newObj
},
...
});
See I explicitly use App[newObjName] = newObj to hook the object onto the namespace, ideally I would like some sort of generic way to name the application namespace in case I use the objController for a different application later.
There has to be some way to do this though I am just not familiar enough with Ember to have encountered it.
Note: on a scale of 1 to JFGI, this question is definitely not a 1. On the other hand it's a free resolved checkmark for anyone that has a moment.
During the initialization phase, Ember will instantiate all of your controllers and inject three properties into each of them - "target", "controllers", "namespace". The "namespace" property is your application.
That said, instead of hard-coding the top-level object:
App[newObjName] = newObj
you can do the following:
this.get("namespace").set(newObjName, newObj);
Note - in order for this to work, your application needs a router. Also, you should define controller classes, not instances. Ember will instantiate all controllers for you. So, this
App.objController = Ember.ArrayController.create({/* code here */});
should be written as
App.ObjController = Ember.ArrayController.extend({/* code here */});
Note the capital "O" in "ObjController".
Consider using injections, which is the preferred way to add dependencies.
Ember.Application.registerInjection({
name: 'fooObject',
before: 'controllers',
injection: function(app, router, property) {
if (property === 'FooObject') {
app.set('fooObject', app[property].create());
}
}
});
So if you define a class as follows:
App.FooObject = Ember.Object.extend({
// ...
});
the injection will create an instance into App.fooObject. Although we still use the namespace App, however only once. You could further do:
Ember.FooObject = Ember.Object.extend({
// ...
});
and then in your App, App.FooObject = Ember.FooObject but I'm not sure if its useful.

Categories