Ok, this may be just a basic JS question. I'm trying to create a model in ember-cli. I've used the blueprints to make the initial file. That gives me
import DS from 'ember-data';
export default DS.Model.extend({
});
How would I add a fixture to this?
This is some code I'm using with fixtures. The main thing is Recipe.reopenClass, Recipe.Fixtures isn't correct.
import DS from 'ember-data';
var Recipe = DS.Model.extend({
title: DS.attr('string'),
steps: DS.attr(),
description: DS.attr('string')
});
Recipe.reopenClass({
FIXTURES: [
{
id: 1,
title: "Spaghetti and meat",
steps: ["Cook noodles", "add meat", "eat the food"],
description: "ITS NOODLES AND MEAT"
},
{
id: 2,
title: "Gyro",
steps: ["get lamb", "eat greek taco"],
description: "ITS A TACO"
}
]
});
export default Recipe;
Then in adapters/application.js
import DS from 'ember-data';
export default DS.FixtureAdapter.extend();
Add this to your Brocfile
app.import({
development: 'vendor/ember-data/ember-data.js',
production: 'vendor/ember-data/ember-data.prod.js'
}, {
'ember-data': [
'default'
]
});
Related
Wow this is hard to find.
I have an existing model in ember and I would like to add a new column. I have't been able to see how to generate this from the CLI, so have manually added it to my component.js and models/post.js. I've added the field to my form and the handlebar to my view. Checking Firebase I can confirm I'm not updating the field.
In Rails I would simply run rails generate migration add_snippet_to_posts snippet:string but doing this in Ember just creates a new model.
model/post.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
createdDate: DS.attr('date'),
text: DS.attr('string'),
snippet: DS.attr('string') #<=manually added this.
});
component.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
createPost: function (model) {
this.sendAction('createPost', model);
// Clear each input field
this.set('newPost.title', null);
this.set('newPost.author', null);
this.set('newPost.text', null);
this.set('newPost.snippet', null); #<= manually added this
}
}
});
How do I do this?
Solved
Needed to update routes/index.js too:
import Ember from 'ember';
export default Ember.Route.extend({
model: function () {
return this.store.findAll('post');
},
actions: {
createPost: function (model) {
let post = this.store.createRecord('post', {
title: model.title,
text: model.text,
author: model.author,
snippet: model.snippet, # <= add this too
createdDate: new Date()
});
post.save();
}
}
});
The official answer would be that you cannot just add an attribute with ember-CLI to a model that has already been created - and at the same time, update everything it may effect throughout your app. You have to manually write the attributes and how they are used in routes/components/templates etc.
That sounds awesome that Rails can just know all that stuff. : )
I'm using Ember 2.5.0 and I have two models service and availability which looks like:
// availability
import DS from 'ember-data';
export default DS.Model.extend({
day: DS.attr('string'),
enabled: DS.attr('boolean'),
startAt: DS.attr('string'),
endAt: DS.attr('string'),
service: DS.belongsTo('service')
});
And service which looks like:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
availabilities: DS.hasMany('availability',
{
defaultValue:
[
{
day: 'saturday',
enabled: false,
startAt: '',
endAt: ''
},
{
day: 'sunday',
enabled: false,
startAt: '',
endAt: ''
}
]
}
)
});
As you can see I was trying to use defaultValue but with no luck. For new route I want to set default values if we are creating a new service record.
Any help is appreciated.
The argument hash that DS.hasMany only accepts two properties: async and inverse. It doesn't accept a defaultValue property though. (source).
But fear not, Eki Eqbal! I think you can accomplish something similar by using your model's ready() hook.
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
availabilities: DS.hasMany('availability', { async: true }), // is the data loaded async?
ready() { // fires when the model is loaded from server or created locally
if (!!this.get('availabilities')) {
// don't set to defaults if availabilities is not null
return;
}
var saturday = this.store.createRecord('availability', {
day : 'saturday',
enabled : false,
startAt : '',
endAt : ''
});
var sunday = this.store.createRecord('availability', {
day : 'sunday',
enabled : false,
startAt : '',
endAt : ''
});
this.get('availabilities').pushObjects([saturday, sunday]);
}
});
In my customer controller I have defined some constant arrays that are used for populating select input (dropdown) options.
import Ember from 'ember';
export default Ember.Controller.extend({
occupations: [
{code: 'student', name: "Student"},
{code: 'worker', name: "Worker"},
{code: 'retired', name: "Retired"},
{code: 'other', name: "Other"}
]
});
Normal solution would be using translationMacro function t() or this.get('i18n').t() around translation key, but they can't be used in such situation as "this" inside object or array will not refer to controller.
What is best practice for solving such situation?
You can make occupations a property:
import Ember from 'ember';
export default Ember.Controller.extend({
i18n: Ember.inject.service(),
occupations: function() {
var i18n = this.get('i18n');
return [
{code: 'student', name: i18n.t('occupations.student') },
{code: 'worker', name: "Worker"},
{code: 'retired', name: "Retired"},
{code: 'other', name: "Other"}
];
}.property()
});
I'm getting the following error while using DS.EmbeddedRecordsMixin when my records have embedded data:
TypeError: Cannot read property 'typeKey' of undefined
I'm using Ember CLI 0.1.2 with Ember 1.7.0 and Ember Data 1.0.0#beta11
My adapters:
Application Adapter - /app/adapters/application.js (RestAdapter):
import DS from 'ember-data';
import config from '../config/environment';
export default DS.RESTAdapter.extend({
namespace: config.APP.RestAdapterNamespace,
host: config.APP.SERVER_LOCATION
});
Adapter in question - /app/adapters/screen.js (screenSlideGroups should be embedded):
import ApplicationAdapter from './application';
import DS from 'ember-data';
export default ApplicationAdapter.extend(DS.EmbeddedRecordsMixin, {
attrs: {
screenSlideGroups: { embedded: 'always' }
}
});
Model: /app/models/screen.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
path: DS.attr('string'),
screenSlideGroups: DS.hasMany('screen-slide-group')
});
Example of data returned from the API:
{
"screen":[
{
"id":1,
"name":"Weather",
"path":"weather",
"screenSlideGroups":[
{
"id":1,
"screen":1,
"slideGroup":1,
"order":1
}
],
"lastUpdated":"2014-09-18T18:26:25.69"
},
{
"id":2,
"name":"Front Lobby",
"path":"frontlobby",
"screenSlideGroups":[
],
"lastUpdated":"0001-01-01T00:00:00"
}
]
}
I also tried removing screen from the embedded record, incase the backwards reference could screw it up, but it didn't make a difference. As far as I can tell, the EmbeddedRecordsMixin adapter I created may not be getting used at all.
Any ideas on what may have gone wrong here?
Turns out I misread the documentation, and DS.EmbeddedRecordsMixin should be on the Serializer, NOT the Adapter.
The correct implementation was as follows:
/app/serializers/screen.js:
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
screenSlideGroups: { embedded: 'always' }
}
});
This is my code (using ember-cli):
app.coffee
`import Ember from 'ember'`
`import Resolver from 'ember/resolver'`
`import loadInitializers from 'ember/load-initializers'`
Ember.MODEL_FACTORY_INJECTIONS = true
App = Ember.Application.extend
modulePrefix: 'dashboard' # TODO: loaded via config
Resolver: Resolver
loadInitializers App, 'dashboard'
`export default App`
adapters/application.coffee
`import DS from 'ember-data'`
ApplicationAdapter = DS.FixtureAdapter.extend()
`export default ApplicationAdapter`
models/mod.coffee
`import DS from 'ember-data'`
Mod = DS.Model.extend
name: DS.attr 'string'
body: DS.attr 'string'
summary: DS.attr 'string'
category: DS.attr 'string'
Mod.reopenClass {
FIXTURES: [
{
id: 1
name: "First mod"
body: "..."
summary: "..."
category: "api"
},
{
id: 2
name: "Second mod"
body: "..."
summary: "..."
category: "api"
}
]
}
`export default Mod`
But in the app nothing is thrown when I run ember serve nor in the browser conole (output:
DEBUG: ------------------------------- vendor.js:27630
DEBUG: Ember : 1.7.0 vendor.js:27630
DEBUG: Ember Data : 1.0.0-beta.8.2a68c63a vendor.js:27630
DEBUG: Handlebars : 1.3.0 vendor.js:27630
DEBUG: jQuery : 1.11.1 vendor.js:27630
DEBUG: ------------------------------- vendor.js:27630
generated -> route:application Object {fullName: "route:application"} vendor.js:27630
generated -> route:index Object {fullName: "route:index"} vendor.js:27630
generated -> controller:application Object {fullName: "controller:application"} vendor.js:27630
Rendering application with default view <dashboard#view:toplevel::ember323> Object {fullName: "view:application"} vendor.js:27630
generated -> controller:index Object {fullName: "controller:index"} vendor.js:27630
Rendering index with <dashboard#view:index::ember339> Object {fullName: "view:index"} vendor.js:27630
Ember Debugger Active
)
In ember inspector it shows me my mod model but with no record
Here is the whole github repo https://github.com/OpenCubes/dashboard/tree/temp
ok 2 things.
first you must generate a route if you are fetching the whole collection. Our actively generated routes don't do this by default. I believe it just has to do with ambiguity and that we don't want to fetch your entire datasource by accident, so we leave this up to the user todo.
// app/routes/mods.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() { return this.store.find('mod'); }
});
second you must use reopenClass when providing fixtures. This is because IE6 + there is not way to properly propagate static/class variables to descendants. So ember implements its own mechanism. At some future point in time setPrototypeOf will be usable and we can defer to that. Until then for ember-cli apps, please use embers sanctioned way.
import DS from 'ember-data';
var Mod = DS.Model.extend({...})
Mod.reopenClass({
FIXTURES: [
...
]
});
export default Mod;
then it works
Update
Hi, I have moved that code to cli and basically, all I had to do was:
create an adapter for Mod:
C:\>ember g adapter mod
Then I went to the source of the generated Mod adapter, and changed the declaration to extend from FixtureAdapter instead of RESTAdapter.
import DS from 'ember-data';
export default DS.FixtureAdapter.extend();
Also, had to change the model declaration, and it's pretty much the same as yours now.
No need to create store or anything.
I don't know really if this is why you're having trouble, but, did you override the adapter in your store? I suspect it might not be using your adapter.
I've made a quick sample (here) that you can use as reference.
Note in the sample below that I'm passing the fixture adapter name as a string to the store (there are other ways to do this as well).
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.Store = DS.Store.extend({
// override default adapter
adapter: 'ApplicationAdapter'
});
[ ... other code ... ]
App.Colour = DS.Model.extend({
name: DS.attr('string'),
hex: DS.attr('string')
});
// settings the fixtures directly in the model class
App.Colour.FIXTURES = [
{id: 1, name: 'red', hex: '#F00'},
{id: 2, name: 'green', hex: '#0F0'},
{id: 3, name: 'blue', hex: '#00F'}
];
Then in my route I query normally:
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('colour');
}
});
This should output the fixture records normally.