Given a tag and post ManyToMany relationship defined as follow:
post.js
import Ember from 'ember';
import Model from 'ember-data/model';
import { hasMany } from 'ember-data/relationships';
export default Model.extend({
tags: hasMany('tag')
}
tag.js
import Ember from 'ember';
import Model from 'ember-data/model';
import { hasMany } from 'ember-data/relationships';
export default Model.extend({
posts: hasMany('post')
}
When adding tags to post using pushObject
let aPost = this.store.findRecord('post', 1),
aTag = this.store.findRecord('tag', 1);
aPost.get('tags').pushObject(aTag); // aPost is not commited yet
How to restore aPost.tags to its initial state?
Related
I'm learning to use ember data. I want to build an image searching app using Pixabay's free API.
I want to send search queries to adapter and get the results in route via model. First of all, I'm not sure how to create adapter for application route. I found many tutorials on ember data, they all built adapters and model for a specific model not on the application route.
app/routes/application.js
import Route from '#ember/routing/route';
export default Route.extend({
model(){
return this.store.findAll('application');
}
});
app/models/application.js
import DS from 'ember-data';
import Model from 'ember-data/model'
const { attr } = DS;
export default Model.extend({
largeImageURL : attr('string')
});
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
host:"https://pixabay.com/api/?key=<API-KEY>&q=<queries>",
pathForType(){
return '/';
}
});
I have problem with making hasMany <=> belongTo relationship to work.
I have articles/show view, when I try to list article's comments but I keep recieving the error pointed in the title.
It's something with belongsTo: DS.belongsTo('article') but I couldn't figure out what it is.
Here are my files.
routes/articles/show.js
import Ember from 'ember';
import RSVP from 'rsvp';
export default Ember.Route.extend({
model(params) {
return RSVP.hash({
article: this.store.find("article", params.id),
comments: this.store.query('comment', { articleId: params.id })
});
}
});
controllers/articles/show.js
import Ember from 'ember';
const { computed: { alias, readOnly } } = Ember;
export default Ember.Controller.extend({
article: alias('model.article'),
comments: alias('model.comments'),
length: readOnly('comments.length')
});
templates/articles/show.hbs
<h3>Comments ({{comments.length}})</h3>
{{#each comments as |comment|}}
<p>Author: {{comment.user.name}}</p>
<p>Somebody said: {{comment.body}}</p>
{{/each}}
adapters/comment.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({});
serializers/comment.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
attrs: {
user: { embedded: 'always' },
article: { embedded: 'always' }
}
});
serializers/article.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
comments: { embedded: 'always' }
}
});
models/article.js
import DS from 'ember-data';
import Ember from 'ember';
const { attr, hasMany } = DS;
const { computed: { gt } } = Ember;
export default DS.Model.extend({
title: attr('string'),
content: attr('string'),
authorName: attr('string'),
authorAvatar: attr('string'),
authorUrl: attr('string'),
comments: hasMany('comment', {async: true}),
hasAvatar: gt('authorAvatar.length', 0)
});
Edit:
I added here the code for comment model as asked in the comments.
models/comment.js
import DS from 'ember-data';
const { belongsTo, attr } = DS;
export default DS.Model.extend({
article: belongsTo(),
user: belongsTo(),
body: attr('string')
});
And here is stacktrace from inspector:
ember.debug.js:16905 Assertion Failed: You need to pass a model name to the store's modelFor method
Error
at assert (http://ffl.com:8000/assets/vendor.js:16268:13)
at Object.assert (http://ffl.com:8000/assets/vendor.js:27196:34)
at assert (http://ffl.com:8000/assets/vendor.js:135212:37)
at Class.modelFor (http://ffl.com:8000/assets/vendor.js:145201:41)
at Class._internalModelForId (http://ffl.com:8000/assets/vendor.js:144337:29)
at Class._pushResourceIdentifier (http://ffl.com:8000/assets/vendor.js:145716:19)
at BelongsToRelationship.updateData (http://ffl.com:8000/assets/vendor.js:142394:36)
at BelongsToRelationship.push (http://ffl.com:8000/assets/vendor.js:142976:14)
at http://ffl.com:8000/assets/vendor.js:145795:20
at http://ffl.com:8000/assets/vendor.js:141943:18
defaultDispatch # ember.debug.js:16905
dispatchError # ember.debug.js:16888
onerrorDefault # ember.debug.js:30389
trigger # ember.debug.js:57833
(anonymous) # ember.debug.js:58717
invoke # ember.debug.js:339
flush # ember.debug.js:407
flush # ember.debug.js:531
end # ember.debug.js:601
run # ember.debug.js:724
join # ember.debug.js:746
run.join # ember.debug.js:21556
hash.success # rest.js:954
fire # jquery.js:3305
fireWith # jquery.js:3435
done # jquery.js:9242
(anonymous) # jquery.js:9484
I checked your issue and repo. The problem was just with comment serializer in Ember.js. It should be:
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
article: { embedded: 'always' },
user: { embedded: 'always' }
}
});
I cloned your project branch refactor-and-upgrade-ember but mirage is not done. So I looked at the code
headTags() {
let article = this.modelFor(this.routeName);
}
This is in routes articles show ,can you try and remove it and try.
I have built a small Ember App. It has a controller which has an action named changeStatus(id). This method access the store and try to change an attribute value. I am relatively new to Ember. I don't know whether best way is to test it with Integration test or unit test? And how to test with either way.
Here is the sample code
Controller: user.js
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
changeStatus(id) {
const oUser = this.store.peekRecord('user', id),
let bCurrentValue = oUser.get('active');
if (bCurrentValue) {
oUser.set('active', false);
} else {
oUser.set('active', true);
}
//oUser.save();
},
}
});
Model: user.js
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default PatientIndexController;
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default Model.extend({
active: attr('boolean'),
});
Unit Test: user-test.js
import {moduleFor, test} from 'ember-qunit';
import Ember from 'ember';
moduleFor('controller:user', 'Unit | Controller | user', { });
test('Toggle user active status', function (assert) {
const contollerUser = this.subject();
contollerUser.send('changeStatus', 1);
assert.equal(contollerUser.store.peekRecord('user', 1).get('active'), 'true or false');
});
but I am not getting how to set some data to store. As when I call the function changeStatus() then it don't know about user model.
How to set a proper test. Thanks in advance.
I have installed Ember Django Adapter(EDA) and I have followed the tutorial and in the template everything is ok but I'm not getting data from my api... but when my model its connect to the api I get the following warning in the console.
WARNING: Encountered "articles" in payload, but no model was found for model name "article" (resolved model name using frontend#serializer:articles:.modelNameFromPayloadKey("articles"))
This is my code:
app/application/serializer.js
import DRFSerializer from '../serializers/drf';
export default DRFSerializer.extend({
});
app/application/adapter.js
import DRFAdapter from '../adapters/drf';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
export default DRFAdapter.extend(DataAdapterMixin , {
authorizer: 'authorizer:django'
});
app/router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('index');
});
export default Router;
app/models/articles.js
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default Model.extend({
title: attr('string'),
body: attr('string')
});
app/index/route.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('articles');
}
});
app/index/template.hbs
{{#each model as |article|}}
<article class="listing">
<h3>{{article.title}}</h3>
</article>
{{/each}}
You should use singular words when naming models, so change your model file to "article.js" and also change in route.js file to this.get('store').findAll('article');
Is there a more elegant way to prevent unauthorized access to an admin-only route than writing this in all of my admin routes?
export default Ember.Route.extend(AuthenticatedRouteMixin, {
beforeModel: function(){
if(!this.get('session.secure.admin')) this.transitionTo("dashboard");
}
});
Perhaps it's possible to extend AuthenticatedRouteMixin itself to make this kind of check?
Thanks!
Why not just make the mixin?
import Ember from 'ember';
import AuthenticatedRouteMixin from 'wherever/it/is'.
const { Mixin } = Ember;
export default Mixin.create(AuthenticatedRouteMixin, {
beforeModel(){
if(!this.get('session.secure.admin')) {
this.transitionTo("dashboard");
}
}
})
And then import it in your routes:
import Ember from 'ember';
import AdminCheckMixin from 'yourApp/mixins/routes/admin-check';
const { Route } = Ember;
export default Route.extend(AdminCheckMixin);