Why ember-cli uses extend instead of create? - javascript

In a new ember App you write first:
var App = Ember.Application.create({
test: 'foo',
...
});
In a new ember-cli App you write first:
var App = Ember.Application.extend({
test: 'foo',
...
});
Why?
( In the second case, I can't read a global property (App.test) from a controller. !? )

This question actually has a lot to do with Ember.Object.
.extend() creates a new class that extends the old one, with class-level properties defined in the hash that is passed in.
.create() create a new instance of the class, with object-level properties defined in the hash that is passed in.
This is why you cannot read the property in the second case. If you want to do that, you will need to do:
var App = Ember.Application.extend({});
App.test = 'foo';
In a plain Ember app, you can create an instance of the App object, because you are going to use it directly.
In an ember-cli generated Ember app, you do not create an instance of the App object, you merely define its class (using .extend()). This is because you do not use it directly, as ember-cli wants the class, so that it may do its own things to it, before it internally instantiates it.

Related

Export a class or an object instance difference

I am confused, or I can say, I have no clue how the exporting actually works.
I have a React app, and I have some protected Routes. On login, I create a Client object instance and pass it to child components through Context, and then consume it.
Recently I saw an approach where the example code exported an object instance from a file directly and just imported it in files they wanted to consume it.
/** My approach **/
export default Example
/** The Object Instance approach **/
export default new Example()
What is the lifecycle of the object instance? Are there any disadvantages with the second approach, because it seems way easier?
If you export the class, with
export default Example
then consumers of the module will be able to instantiate their own instances, and each instance will be able to have its own data. For example
// 1.js
import TheClass from './TheClass';
const tc1 = new TheClass();
tc1.foo = 'foo';
// 2.js
import TheClass from './TheClass';
const tc2 = new TheClass();
tc2.foo = 'bar';
Both modules can continue to use tc1 and tc2 completely independently, since they're separate instances.
But if the original module exports an instance rather than a class, then all consumers of the module are forced to use the same instance:
// 1.js
import theInstance from '...';
theInstance.foo = 'foo';
// 2.js
import theInstance from '...';
// might not be a good idea to do theInstance.foo = 'bar' here
// because that will affect 1.js as well
// and will affect any other modules that imported the instance
In short - exporting the class is more reusable than exporting the instance. Sometimes potential reusability is something a script-writer will consider important, and sometimes it isn't. (And sometimes, even if you don't consider it useful initially, you may encounter a situation later that forces you to reconsider.)
And sometimes you want to make sure that there's only one instance ever in a script, in which case
export default new Example()
is a way to accomplish it.

ES6 Parent class overrides child prototype

I decided to write ES6 class for Express server, but extended Express overrides child prototype, and there is no way to use methods and props that defined outside constructor. See code:
import Express from 'express'
export default class Server extends Express {
constructor(options) {
super(options.expressOptions || {})
super.use(cookieParser()) // TypeError: (intermediate value).use is not a function
this.use(bodyParser.json()) // This definition works cause of overridden prototype
this.use(Express.static('static'))
this.test() // TypeError: this.test is not a function
this.test1 = '123' // Contains in Server final prototype
}
test() {
console.log('test')
}
}
And problem with super class definition. I don't know how to save child prototype. It's will be very precious if you help.
Having looked again at this, I see the problem.
express is not a constructor.
You are treating express as if it were a constructor that you call using new Express. This is not how it works: you just call it with, for example, const app = express(). In fact, express is a function (here's the source code) that creates the object for you, in an old-fashioned (non-ES6) way.
As far as I am aware, it is not possible to subclass any of the core Express objects. You could, I guess, use classes to wrap the Express framework objects, but that doesn't seem intuitive to me.

Emberjs Router with requirejs

When building a relatively large application, how should I define my router? More specifically, if using requirejs I have the following code:
main.js
define('application',['routes/app_router'], function(router){
return Ember.Appcliation.create(
LOG_TRANSITIONS:true,
...
});
requirejs('application',function(application){
var App = window.App = application;
...
}
and in the routes/ I have app_router.js
define('app_router',['ember'],function(){
...
});
So should I pass an app to my app_router to set the App.Router.map... method or should I return a Ember.Router.map(...)? If the first variant is chosen then for sure, the dependencies change.
In other words, should I create an "empty" Ember.Application and pass it to the router so it can define the App.Route.map(... method, since it has reference to this, like this.route\this.resource..., or should I invoke Ember.Router.create() then invoke the map function on it, then return this from the module and set it to App.Router = router.
So should I pass an app to my app_router to set the App.Router.map... method or should I return a Ember.Router.map(...)? If the first variant is chosen then for sure, the dependencies change.
I'd go with the 2nd variant.
In other words, should I create an "empty" Ember.Application and pass it to the router so it can define the App.Route.map(... method, since it has reference to this, like this.route\this.resource..., or should I invoke Ember.Router.create() then invoke the map function on it, then return this from the module and set it to App.Router = router.
Neither. You should let ember create the router itself. All your code should be doing is calling App.Router's map fx. I'm no require.js expert, but something like this should work:
//Define a fx that specifies your applications routes
define('routes',['ember'], function(){
return function() {
this.route("about");
}
});
// Pass that custom routes fx to App.Router.map before routing begins
define('application',['routes'], function(routes){
return Ember.Application.create({
LOG_TRANSITIONS: true,
ready: function() {
this.Router.map(routes);
}
});
Here's a jsfiddle showing the basic concept, without require.js of course.

Set of CoffeeScript/JavaScript classes and methods available to rest of Rails app

I'm using Rails 3.2.9. When I add CoffeeScript code to a .js.coffee file in the /app/assets/javascripts directory, I get the resulting JavaScript in all of my webpages. The problem is all the JavaScript is wrapped in:
(function() {
// my code
}).call(this);
So any methods I define are not visible in any other CoffeeScript code I write in other files. What's the proper way to write a set of reusable CoffeeScript classes and methods with Rails?
The simplest thing to do is to namespace all your classes. If your application is called "app" then in your initialization code before anything else happens:
// Set up the namespace.
window.app = { }
and then in all your .coffee files:
class app.Pancakes
#...
Then you'd have a global namespace and you'd reference everything through that namespace:
pancakes = new app.Pancakes
Similarly for simple functions:
app.where_is = (pancakes, house) -> ...
# And elsewhere...
x = app.where_is(...)
There are various ways of setting up and partially hiding the namespace but they're all variations on the above and simple namespacing plays nicely with the Rails asset pipeline.
Also, you can define classes within the coffeescript files like this:
class this.Person
constructor: (attr = {}) ->
...
In that way, the definitions are attached to the global namespace.

Can I use AngularJS to handle and load my objects

I've got some CoffeeScript classes which I use and extend in my code. How can I use angularjs to not have to create the usual module cruft like
MyNamespace = MyNamespace || {}
MyNamespace.SuperClass = class
and in a different file
MyNamespace = MyNamespace || {}
class ChildClass extends MyNamespace.SuperClass
MyNamespace.ChildClass = ChildClass
Could I simply write
angular('MyModule').factory, 'SuperClass', () ->
class SuperClass
constructor: (#id) ->
return SuperClass
and extend from that class via
angular('MyModule').factory, 'ChildClass', ['SuperClass', (SuperClass) ->
class ChildClass extends SuperClass
constructor: (id) ->
super(id)
return ChildClass
]
My problem is actually that Im using CoffeeScript to compile all objects into a single file. Now if a childclass is above the baseclass, the baseclass will be undefined and I'll get an error. I'm looking for an elegant and easy way how to solve this.
If you use Angular's DI system, it should ensure that your classes are instantiated in the correct order, regardless of which is loaded first. Is there actually an issue with your example?
With Angular you can do away with putting your classes in namespaces, since the name of your module / service can be qualified and effectively serve the same purpose.
What I don't think Angular will help with is ensuring that your super class code is run before your child class code. For that there seems to be about 8000 ways of solving the problem and none of them standard - requireJs, coffeetoaster, brunch, grunt, cake.....
I use grunt, and specify the order in which I want to concat my coffeescript.

Categories