How do I configure a many-to-many relationship?


#1

I have a many to many relationship between users and accounts. When I create these records on sign up, I am able to see the id of the account I just created in the json for the users I just created, but I am not able to see the user ids in the account json I just created. I am trying to create these records with the associated ids. I am using Sinatra for the back end. This is my first time asking a question so my apologies if my question isn’t clear or code snippets aren’t formatted correctly. Here’s what I have:

user model

export default DS.Model.extend({

...

accounts: DS.hasMany('account'),

...
});

account model

export default DS.Model.extend({
...

users: DS.hasMany('user'),

...

})

sign-up route

model () {
    console.log("at model() on route for /sign-up");

    let account = this.store.createRecord('account');
    let dentist = this.store.createRecord('user');
    let officeContact = this.store.createRecord('user');


    let item = RSVP.hash({
        dentist: dentist,
        officeContact: officeContact,
        account: account,
    });

    return item;

},

actions: {
    register (item) {
        console.log('at register action on route for /sign-up');


        item.account.save()
            .then(function() {
                item.account.get('users').addObject(item.dentist);
                item.account.get('users').addObject(item.officeContact);

                item.dentist.save().then(function() {
                    item.officeContact.save()
                })
            }).then(() => this.transitionTo('/'))


        console.log("//ACCOUNT//");
        console.log(item.account);
        console.log("//DENTIST//");
        console.log(item.dentist);
        console.log("//OFFICE CONTACT//");
        console.log(item.officeContact)
    }
}
})

POST users

post '/v1/users' do
request.body.rewind
json = JSON.parse(request.body.read)
puts "#{json}"
account = Account.first(id: json['user']['accounts'][0].to_i)
json['user'].delete('accounts')
json['user'].delete('password_confirmation')
puts "USER #{json['user']}"
puts "USER ACCOUNT #{json['user']['type']}"

user = User.create(json['user'])
user.accounts << account
if user.save == false
  user.errors.each do |err|
    puts "NEW USER ERROR #{err}"
  end
  halt 400, '{"message": "User not created."}'
end

{user: user}.to_json
end

POST Account

request.body.rewind
json = JSON.parse(request.body.read)
puts "ACCOUNT #{json['account']}"
account = Account.create(json['account'])
if account.save == false
  account.errors.each do |err|
    puts "ACCOUNT #{json['account']}"
    puts "NEW ACCOUNT ERROR #{err}"
  end
  halt 400, '{"message":"Could not create Account"}'
end
puts "ACCOUNT #{json['account']}"

{account: account}.to_json
 end

#2

It would be helpful if you could include the JSON returned by your backend for POST /users and POST /accounts. You could get them easily in network tab of browser’s developer tools.


#3

Thank you for responding.

Here’s the JSON for POST /users:

{"user"=>{"first_name"=>"jkkj", "last_name"=>"jj", "email"=>"j@sss.com", "info"=>nil, "type"=>"OfficeContact", "password"=>nil, "created_at"=>nil, "updated_at"=>nil, "accounts"=>["10"]}}

POST /accounts

{"name"=>"test1", "registration_info"=>nil}

Registration info isn’t required.


#4

This seems fine. Are you sure your Serializer is handling relationship correctly? Is the relationship set up working on GET?

Are you trying to determine if the relationship setup has worked by your console.log calls in register action? If you are not using client-side generated IDs, your records won’t have IDs at that point of time cause the requests are async. I would recommend using ember-inspector.


#5

I have ember inspector. The only id that shows is the one for the record itself. I am able to access the account id for the user by using ‘user.record.id’(not sure if that’s the way to go) but I am not able to access the user data for accounts.

This is my serializer for accounts:

export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
    attrs: {
        users: { serialize: 'ids' }
    }
});

user serializer:


export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
    attrs: {
        accounts: { serialize: 'ids' }
    }
});

#6

Would be helpful if you could setup an ember-twiddle reproducing your issue. Could you please try to do so? You could use ember-cli-mirage in ember-twiddle for mocking your api. There is a boilerplate twiddle for mirage.


#7

I’m not sure if I put too much or too little info, please let me know if there’s anything I need to add. Here’s my twiddle: https://ember-twiddle.com/0c3c7e88ad32e76742800a9fccc7502b?openFiles=mirage.config.js%2C


#8

Your ember-twiddle wasn’t working. Maybe mirage boilerplate is a little bit confusing to get started with. I’ve written an ember-twiddle with your basic example which is working: https://ember-twiddle.com/89b40ca9d44a34537fe296e087a52b83?openFiles=templates.sign-up.hbs%2C Please start from there and try to reproduce your issue with at least changes as possible.

Some side notes I’ve noticed when looking over your twiddle:

  • Do you know ember-bootstrap? It’s great to setup bootstrap forms with validation etc. https://www.ember-bootstrap.com/#/components/forms
  • store.createRecord does not return promises. It’s a sync function. Therefore you don’t need to wrap the returned data in a RSVP.hash().
  • You should use pushObject instead of addObject for performance reasons if you know that the object it’s not present in the array yet.

#9

This was great! Thank you. My issue was that I couldn’t see the accounts associated with the user but when I change the twiddle to return all ‘users’ and change the templates accordingly and it displays the account associated with the users. However, when I apply it to my app, the correct information is displayed but when i refresh it, the ‘li’ elements disappear. For example, the accounts route no longer shows the users and vice versa. I’m not sure if that would be a different topic.


#10

Good to hear that’s working now for you.

I noticed yesterday evening that you have opened the same question twice at StackOverflow (1, 2). This is not a respectful practice to the volunteers you are asking about help IMO.


#11

I tried SO first and put 2 questions because I didn’t feel as if my first question was clear enough. But I didn’t get a response on either one so I tried this site. Again, I’m new to this so just trying to figure out what works. I’ll delete the questions. But thanks again for your help!