In tutorial
https://www.howtographql.com/vue-apollo/1-getting-started/
there is presented new HttpLink syntax, but in official docs
https://www.apollographql.com/docs/link/links/http/
function createHttpLink is applied.
None of these two sources describes the differences between these methods.
There is no fundamental difference between the two.
If you look at the apollo-link-http package source here, you can see that the exported createHttpLink method returns a new instance of the ApolloLink class initialized with the options you passed to createHttpLink (lines 62-194).
At the end of the same file, you can see that the package also exports the HttpLink class, which extends the ApolloLink class (lines 256-261):
export class HttpLink extends ApolloLink {
public requester: RequestHandler;
constructor(opts?: HttpLink.Options) {
super(createHttpLink(opts).request);
}
}
As you can see from the code above, when you create an apollo http link by creating a new instance of the HttpLink class, the options you pass to the constructor are internally passed on to createHttpLink, which returns an instance of ApolloLink as mentioned above, and that instance's RequestHandler is passed on to (i.e. copied) to the new HttpLink instance's parent, which is also an instance of ApolloLink (see lines 96-124 here for a peek at ApolloLink's own constructor).
Note that the apollo-link-http package's own docs do NOT mention the new HttpLink syntax, so I would stick to the createHttpLink syntax for future compatibility.
Related
I'm new to Ember and it keeps confusing me about the difference between this.get() and Ember.get(). Can someone explain them briefly?
Welcome to Ember ;-)
Every object that extends Ember Observable mixin supports the get() method (among others).
When you call this.get(), the this must refer to such an object (Route, Controller, Component, your own class that extends Ember.Object and so on). Calling get() on plain object would cause a failure. Let me show the difference:
const emberObjectInstance = Ember.Object.create({
name: 'Bala'
});
emberObjectInstance.get('name'); // returns 'Bala'
const plainObject = { name: 'Bala'};
plainObject.get('name'); // causes a failure since get() is not a function
However, using Ember.get() successes in both cases:
Ember.get(emberObjectInstance, 'name'); // returns 'Bala'
Ember.get(plainObject, 'name'); // returns 'Bala', too
which can be also written with imports as follows
import { get } from '#ember/object';
get(emberObjectInstance, 'name'); // returns 'Bala'
get(plainObject, 'name'); // returns 'Bala', too
Note: not to forget, calling either of get() makes computed property get computed (in the most common cases, I don't want to dive deep now - lazy computation, volatile extensions etc), but for the sake of understanding the difference, we can work with plain values.
From own experience, I am using Ember.get() everywhere I know a plain object might be the object whose property I need to retrieve. A nice example is setupController() hook into which I may pass plain object from my unit tests to test setupController()'s functionality.
// some route:
setupController(controller, model){
this._super(...arguments);
const name = Ember.get(model, 'name'); // ***
controller.set('isNamePresentOnSetup', Ember.isPresent(name));
}
// in my unit tests I can use plain object:
...
const modelMock = { name: 'Bala' }; // plain object is enough because I use Ember.get instead of model.get() (see ***)?
const controllerMock = Ember.Object.create(); // has to be Ember.Object since I use controller.set() within setupController()
subject.setupController(controllerMock, modelMock);
assert.ok(controllerMock.get('isNamePresentOnSetup'), "property 'isNamePresentOnSetup' set up correctly if model name is present");
...
I could also user Ember.set(controller, 'isNamePresentOnSetup', Ember.isPresent(name)) and then pass plain controller mock into setupController(), too.
I think this is a good start since you are new in Ember and I am sure Ember gurus would have much more to add.
Relevant Ember docs:
https://guides.emberjs.com/v2.9.0/object-model/
https://guides.emberjs.com/v2.9.0/object-model/computed-properties/
https://guides.emberjs.com/v2.9.0/object-model/reopening-classes-and-instances/
UPDATE:
Using get() with chained paths works different than working with POJOs.
For example in objectInstance.get('a.b.c') if b is undefined the return value is undefined. Converting this to objectInstance.a.b.c when b is undefined would instead raise an exception.
There is none. foo.get('bar') is equivalent to Ember.get(foo, 'bar'). However because foo.get is defined on Ember.Object you can only call .get() on Ember Objects. Ember.get() will work on all ember objects. On Ember Objects Ember.get(foo, 'bar') is equivalent to foo.get('bar'), on every other object its equivalent to foo['bar'].
Please note that using Ember.get() or this.get() is not needed anymore for most use cases if running Ember >= 3.1, which was released in April 2018. You could now use native ES5 getters. A quick introduction to this change could be found in release notes for Ember 3.1. It's discussed more in detail in RFC 281.
There is a codemode available that helps you transition to ES5 getters: es5-getter-ember-codemod It could be run as part of ember-cli-update.
Please not that using Ember.get() or this.get() is not deprecated. It's still needed for some edge cases, that are listed in release notes linked above:
In fact there are several cases where you must still use get:
If you are calling get with a chained path. For example in this.get('a.b.c') if b is undefined the return value is undefined. Converting this to this.a.b.c when b is undefined would instead raise an exception.
If your object is using unknownProperty you must continue to use get. Using an ES5 getter on an object with unknownProperty will cause an assertion failure in development.
Ember Data returns promise proxy objects when you read an async relationship and from other API. Ember proxy objects, including promise proxies, still require that you call get to read values.
Please note that there is a special case if using ember-changeset. It provides it's own .get() implementation. Therefore Ember.get(this, 'value') and this.get('value') have different results if this is an ember-changeset. You find more information on that case in documentation of ember-changeset.
I have an ember app built using ember-cli conventions and I would like to spy on a util function using sinon. The problem is I don't know how to reference the object that the function is defined on.
I have a function defined as follows in app/utils/report-error.js:
reportError = function(err) {
# ...
};
export default reportError;
And then I import that function elsewhere as follows:
import reportError from '../utils/report-error';
Is it possible to spy on this function using sinon? Normally I would refer to the object on which the function is defined:
sandbox = sinon.sandbox.create();
sandbox.spy(someObject, "reportError");
But what is the someObject of a bare function that gets imported?
I realize I could just put the function on an object and import the object, but that means that everywhere the function is used, I need to reference the receiver object too, which seems messy.
When the I look at the javascript that is produced after the import and export statements are transpiled, there is actually an object with a function on it:
reportError['default']();
But any mentions to reportError get similarly transpiled and there doesn't seem a way to refer to the host object of the dependency.
Thoughts?
I noticed that in the app.js file produced by Ember CLI (v0.1.12), they're using:
var App = Ember.Application.extend({...})
but in the introduction guide, they're using:
window.App = Ember.Application.create({...});
Is there any difference in outcome between these two (create vs. extend) ways of creating an Ember application?
As documented in the Ember documentation extend Creates a new subclass, while
create Creates an instance of a class.
The main difference is that by using extend
you can override methods but still access the implementation of your
parent class by calling the special _super() method
but create does not afford that ability.
The linked docs have good code examples specifically with regards to your question.
See
The create() on line #17 creates an instance of the App.Soldier class.
The extend() on line #8 creates a subclass of App.Person. Any instance
of the App.Person class will not have the march() method.
and the code proceding that quote.
I want to add a mixin to an Ember class which has already been created. (The class is defined in a library, actually Ember itself; it's LinkView).
I see that we can do mixin.apply(obj), but this applies the mixin to an instance of the class. I want to add the mixin to the class, so it's automatically mixed-in to all newly created objects.
I attempted to override the init method of the class, using reopenClass, and do mixin.apply(this) there, to apply the mixin to the instance, and then call the original init method, but this does not seem to work because the mixin wiring is set up in the init method and it's already too late by the time I can get to it.
reopenClass does not seem to accept a mixin argument like extend does. Its code seems to suggest that it's doing something with mixins, but whatever it is it doesn't work:
a = Ember.Object.extend().reopenClass(Ember.Mixin.create({mixval: 1});
a.create().get('mixval'); // undefined
I know that I could create my own class with MyLinkView = Ember.LinkView.extend(mixin, ..., but unfortunately the original class name is referenced explicitly within the library, so I really would prefer to figure out how to extend that original class with my mixin.
I experimented with Ember.LinkView = Ember.LinkView.extend(mixin, .... This somehow seems dangerous, although it seems to work. But in this particular case it doesn't help me since the reference within the Ember code (in the definition of the {{link-to}} helper) is to an internal version of the class, not the fully qualified Ember.LinkView.
Any ideas?
The solution is simply
Klass = Parent.extend({init: {...}});
Mixin = Ember.Mixin.create({init: {...}});
Klass.reopen(mixin);
Everything works as expected, including the super chain. In other words, a call to Klass.create().init() will call the mixin's init, and a call to super from there will call the original Klass#init.
In the course of researching this question, I discovered something interesting about reopen. Even if the argument is not a mixin, it is treated as one (internally, it actually creates a temporary one). This means that if you do
Klass.reopen({
init: function() {
this._super.apply(this, arguments);
}
});
The call to super is actually calling the original init, not the init in the parent class. In other words, specifying init in a reopen does not replace the existing init on the class, it more or less layers on top of it. I can't see this behavior documented anywhere in the Ember docs, but it does seem useful in the right situation.
I came across at this thread, does anybody know how to do this in Play! 1.2.4? Thanks.
The same effect is not quite possible, I think. You can of course reference classes in your Models package by using fully qualified names (models.YourModel) to access enumerations, for example.
Anything you add in the renderArgs scope in your controller will be available in the template, plus there are some implicit objects that are always in use (see Play framework documentation for full listing). For example the play.Play object contains all kinds of useful stuff.
With #Before and #With annotations you can set up a controller used by multiple other controllers to have objects "globally" available - see Interceptions.
Even better, create a super controller extending Controller. Afterwards, let all your controllers extends your SuperController.
class SuperController extends Controller {
#Before
public static function before() {
// Set global variables using renderArgs
}
}
class MyController extends SuperController {
public function myMethod() {
// Do whatever your method does.
}
}
Check out the documentation : http://www.playframework.org/documentation/1.2.4/controllers#result