I have the following models:
App.Company = DS.Model.extend({
name: DS.attr('string'),
accounts: DS.hasMany('App.Account', {
inverse: 'company'
})
});
App.Account = DS.Model.extend({
login: DS.attr('string'),
first_name: DS.attr('string'),
last_name: DS.attr('string'),
email: DS.attr('string'),
password: DS.attr('string'),
password_confirmation: DS.attr('string'),
company: DS.belongsTo('App.Company')
});
The company is defined as being embedded in the account:
DS.RESTAdapter.map('App.Account', {
company: { embedded: 'always' }
});
When I create a new account, the company data is correctly embedded in the account data and I'm seeing the POST request that I expect on the server side:
Started POST "/accounts" for 127.0.0.1 at 2013-06-27 13:30:53 +0200
Processing by AdminUsersController#create as JSON
Parameters: {"account"=>{"login"=>"fsdfdf", "first_name"=>"fgdfgh", "last_name"=>"fsfdsfdsfsd#fgfdgdfgf.de", "email"=>"dsfdsgds#frgdfgfgdfg.de", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "company"=>{"name"=>"gfdhgtrhzrh"}}}
However, I'm also seeing an additional POST request for the company itself:
Started POST "/companies" for 127.0.0.1 at 2013-06-27 13:30:53 +0200
Processing by CompaniesController#create as JSON
Parameters: {"company"=>{"name"=>"gfdhgtrhzrh"}}
I'm setting up the models as follows:
this.transaction = this.get('store').transaction();
var account = this.transaction.createRecord(App.Account, {});
account.set('company', this.transaction.createRecord(App.Company, {}));
When the user clicks save, I simply commit the transaction:
this.transaction.commit();
Is that a bug or am I doing something wrong? Spent quite some time on that already...
Thanks for help!
this.transaction.createRecord(App.Company, {})
The code fragment creates the separate company entity. Is it really such a surprise there is a post action for it?
As far as I remember that was never actually supported in the (old) version of Ember Data I used back then. Newer versions handle that case differently anyway so I'd say this is outdated and close it.
Related
After seeming to bang my head on a wall for what seems to be a simple problem I thought it best to ask for some help.
I am creating an EmberFire application that allows users to authenticate using the simple login. Once authenticated the user can store particular items for later retrieval.
I have models defined as so:
USER:
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
dateOfBirth: DS.attr('date'),
registeredAt: DS.attr('date'),
compentencies: DS.hasMany('competency', { async: true })
});
COMPETENCY:
export default DS.Model.extend({
title: DS.attr('string'),
endDate: DS.attr('date'),
user: DS.belongsTo('user', { async: true })
});
These are stored in the firebase db in a denormalised for as I would like them to be.
My issue arises on retrieval of persisted data. I am not sure how I am supposed to lock the competencies down to a particular user?
The way the rules cascade in FireBase I am not sure if this is even possible in this form but it does not seem right that I would have to store each competency in an embedded form under each user node.
I know that I could just allow read access to all 'Competency' models with this.store.find('competency') and then filter them on the client but that does not fit the security I would expect.
Any help would be great thanks.
Ryan
To only allow read access to a competency if the competency belongs to the user who is currently logged in you can use $competencyId (you can replace "competencyId" with any valid string). Using $competencyId limits access to a specific node under competencies/ instead of allowing access to the entire tree.
"rules": {
"competencies": {
"$competencyId": {
".read": "data.child('user').val() === auth.uid"
}
}
}
I am trying to serialize a user object and pass it to an ember client. My app uses the RESTserializer.
A user object has_one address object. There is no separate endpoint for just the address so I can't just provide a foreign key id and sideload it.
The JSON received just includes address as an object and looks something like this:
{"user":
{
"id":"5",
"name":"Andrew",
"address":
{
"id":"3",
"addressable_id":"5",
"street":"1",
"country_code":"US"
}
}
On the ember side I have a user model
App.User = DS.Model.extend({
name: DS.attr('string'),
address: DS.belongsTo('address'),
//hasOne via belongsTo as suggested by another SO post:
//http://stackoverflow.com/questions/14686253/how-to-have-hasone-relation-with-embedded-always-relation
});
and an address model
App.Address = DS.Model.extend({
addressable_id: DS.attr('string'),
street: DS.attr('string'),
country_code: DS.attr('string'),
user: DS.belongsTo('user')
});
Currently running this code throw an error in the console:
TypeError: Cannot read property 'typeKey' of undefined
which can be fixed by removing the
address: DS.belongsTo('address'),
line in the user model but then the relationship doesn't load properly.
So what am I doing wrong configuring this? I am having a hell of a time finding up to date documentation on this.
You need to use the DS.EmbeddedRecordsMixin on a per-type serializer.
In your case, you would need to do the following :
App.UserSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
address: {embedded: 'always'}
}
});
as explained in this excellent answer.
I have the following model
MyApp.Company = MyApp.User.extend
companyName: DS.attr('string')
companyEmail: DS.attr('string')
cvr: DS.attr('number')
services: DS.hasMany('service')
Which has many services
MyApp.Service = DS.Model.extend
name: DS.attr('string')
description: DS.attr('string')
content: DS.attr('string')
avatar: DS.attr('string')
smallAvatar: DS.attr('string')
serviceField: DS.belongsTo('serviceField')
companies: DS.hasMany('company')
Now i have a panel, where the user adds services to his company, and end up pushing the save button which triggers this action in my controller.
saveAccount: ->
#get('model').save()
Now my problem is that, with the new services added, i would expect the data in the put request to look something like this.
company: {
company_email: "fsfsdfsdf"
company_name: "Elvar's biks"
cvr: 389298498
services: [1,4,2]
}
But the "services" is missing; am i expecting a wrong json structure? If so, how should i tackle this?
Might be worth noting, that all the object are created before hand, so the client i choosing from existent services, i just need to create the relations server side.
Looks like you are trying to set up a many to many relationship, so you'll want to use a bridge table/model here.
First, create a new model called CompanyService:
MyApp.CompanyService = DS.Model.extend
company: DS.belongsTo 'company'
service: DS.belongsTo 'service'
Next, update your company model:
MyApp.Company = MyApp.User.extend
companyName: DS.attr('string')
companyEmail: DS.attr('string')
cvr: DS.attr('number')
companyServices: DS.hasMany('companyService', {async:true})
Then, update your service model:
MyApp.Service = DS.Model.extend
name: DS.attr('string')
description: DS.attr('string')
content: DS.attr('string')
avatar: DS.attr('string')
smallAvatar: DS.attr('string')
serviceField: DS.belongsTo('serviceField')
companyServices: DS.hasMany('companyService', {async:true})
From here you'll need to modify whatever backend setup (Rails?) you have going to accommodate this new model relationship.
Hope that helps!
I'm having a ton of trouble with updating a model in my Ember application. I can't seem to find good documentation that describes how to update my app. The following code is what I'm trying. This sends an update to /playlists/:playlist_id, unfortunately it doesn't send the updated songs as well... is there some callback for pushObject that I can't find? Am I trying trying to save the wrong thing?
App.PlaylistIndexController = Ember.ObjectController.extend({
actions: {
addSong: function(song) {
songs = this.get('songs');
songs.pushObject(song);
this.get('model').save();
}
}
});
App.Playlist = DS.Model.extend({
name: DS.attr('string'),
songs: DS.hasMany('song'),
});
App.Song = DS.Model.extend({
name: DS.attr('string'),
artist: DS.attr('string'),
playlist: DS.belongsTo('playlist'),
});
I am working on an application using ember.js and a couch DB backend. So far, i used ember-resource as database driver, but I am considering switching to ember-data, since this seems to be more sustainable.
Since I am working with couch DB, I am using the Couch DB-Adapter.
The documents in my database contain complete object structures, so I have to specify embedded objects in the database driver.
But although I am specifying my sub-objects as embedded, ember-data seems to fetch these objects with separate requests, instead of just getting them out of the main json.
My object definitions are as follows:
App.UserProfile = DS.Model.extend({
type: DS.attr('string'),
fullname: DS.attr('string'),
email: DS.attr('string'),
pictureUrl: DS.attr('string'),
social: DS.hasMany('App.SocialWebAccount', { embedded: true }),
.....
});
App.SocialWebAccount = DS.Model.extend({
profile: DS.belongsTo('CaiMan.UserProfile'),
site: DS.attr('string'),
account: DS.attr('string'),
.....
});
and the server data ist something like this:
{
"_id": "thoherr",
"_rev": "55-d4abcb745b42fe61f1a2f3b31c461cce",
"type": "UserProfile",
"fullname": "Thomas Herrmann",
"email": "test#thoherr.de",
"pictureUrl": "",
"social": [
{
"site": "socialFacebook",
"account": "thoherr"
},
{
"site": "socialXing",
"account": "Thomas_Herrmann7"
},
{
"site": "socialEmail",
"account": "test#thoherr.de"
}
]
}
After loading, the UserProfile does contain an ArrayProxy for my social data, which is populated by three entries, but they are all undefined instead of instances of SocialWebAccount!
If i try to access this array, ember-data seems to do a separate database access to fetch the data, which then leads to an error because the couch DB-adapter accesses an _id field, which is not available in undefined....
What am i missing?
I thought the "embedded" flag signals that the data is already in the json and the objects can be instantiated from the json?
Why does ember-data try to fetch the embedded data?
Any hint?
It seems that the embedded option has changed recently. I found some information in the test files on the ember-data github.
In these test files, the embedded content is defined like this
Comment = App.Comment = DS.Model.extend({
title: attr('string'),
user: DS.belongsTo(User)
});
Post = App.Post = DS.Model.extend({
title: attr('string'),
comments: DS.hasMany(Comment)
});
Adapter = DS.RESTAdapter.extend();
Adapter.map(Comment, {
user: { embedded: 'always' }
});
or
Adapter = DS.RESTAdapter.extend();
Adapter.map(Comment, {
user: { embedded: 'load' }
});
'always' seems to be used for embedded data without ids (your case),eg
id: 1,
title: "Why not use a more lightweight solution?",
user: {
name: "mongodb_expert"
}
'load' seems to be used for embedded data with ids
id: 1,
user: {
id: 2,
name: "Yehuda Katz"
}
Hoping it will help in your particular case. I've had a lot of trouble with hasMany relationships recently (I had to modify my adapter to get it work)