I am having an issue with trying to save many to many relationships in Ember.js using ember-data and rails. The association works fine on the ember side of things, however when I try to commit the transaction it will not include the list of new associations when submitting to rails. Any help would be much appreciated, I've been tearing out my hair trying to find an example application that does something this simple on github but I can't seem to find one.
Here is a dumbed down version of my Ember code:
App.Store = DS.Store.extend
revision: 11
adapter: DS.RESTAdapter.create
url: '/api'
App.Router.map ->
@resource 'rosters'
@resource 'users'
App.User = DS.Model.extend
rosters: DS.hasMany 'App.Roster'
App.Roster = DS.Model.extend
users: DS.hasMany 'App.User'
App.RostersEditRoute = Ember.Route.extend
setupController: (controller, model) ->
controller.set 'users_list', App.User.find()
App.RostersEditView = Ember.View.extend
userCheckbox: Em.Checkbox.extend
checkedObserver: ( ->
users = @get 'roster.users'
if @get 'checked'
users.addObject @get 'user'
else
users.removeObject @get 'user'
@get('controller.store').commit()
).observes 'checked'
Edit form:
each user in users_list
label.checkbox
view view.userCheckbox rosterBinding="current_roster" userBinding="user" | #{user.full_name}
Rails Backend (Using Inherited Resources and Active Model Serializer gems):
class User < ActiveRecord::Base
has_many :rosters_users
has_many :rosters, through: :rosters_users
accepts_nested_attributes_for :rosters
end
class RostersUser < ActiveRecord::Base
belongs_to :user
belongs_to :roster
end
class Roster < ActiveRecord::Base
has_many :rosters_users
has_many :users, through: :rosters_users
accepts_nested_attributes_for :users
end
module Api
class RostersController < BaseController
end
end
module Api
class UsersController < BaseController
end
end
module Api
class BaseController < ActionController::Base
inherit_resources
respond_to :json
before_filter :default_json
protected
# Force JSON
def default_json
request.format = :json if params[:format].nil?
end
end
end
class UserSerializer < BaseSerializer
has_many :rosters, embed: :ids
end
class RosterSerializer < BaseSerializer
has_many :users, embed: :ids
end
So like I said, the association works fine on Ember but rails doesn't seem to be getting the new association data. When I check out the XHR tab in the web inspector, I see it only sent this:
Request Payload {"roster":{"created_at":"Thu, 21 Mar 2013 23:16:02 GMT","team_id":"1"}}
And I am returned with a 204 no content error because nothing changed.
Despite the fact that it's possible to set up matching hasMany
relationships, Ember Data doesn't actually support many to many relationships yet (see this issue). What you can do for now is decompose the relationship using a membership model.
App.User = DS.Model.extend
rosterMemberships: DS.hasMany 'App.RosterMembership'
App.RosterMembership = DS.Model.extend
user: DS.belongsTo 'App.User'
roster: DS.belongsTo 'App.Roster'
App.Roster = DS.Model.extend
rosterMemberships: DS.hasMany 'App.RosterMembership'
Now you can use createRecord()
and deleteRecord()
with the membership model to add and delete relationships.
Unfortunately, in this example, it's not so easy to bind to the collection of rosters for a particular user. One work-around is as follows:
App.User = DS.Model.extend
rosterMemberships: DS.hasMany 'App.RosterMembership'
rosters: ( ->
@get('rosterMemberships').getEach('user')
).property '[email protected]'
App.RosterMembership = DS.Model.extend
user: DS.belongsTo 'App.User'
roster: DS.belongsTo 'App.Roster'
relationshipsLoaded: ( ->
@get('user.isLoaded') and @get('roster.isLoaded')
).property 'user.isLoaded', 'roster.isLoaded'
If you bind to user.rosters
, then your template should update when relationships are created or destroyed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With