Search code examples
ember.jsfirebaseemberfire

How to access a model from another controller in Ember


This is a novice question: I'm creating a new Chapter record in the Store (Ember-data). I want to add the Chapter ID to the User.chapters property of the User Model record.

App.Book = DS.Model.extend({
  name: DS.attr('string'),
  icon: DS.attr('string'),
  description: DS.attr('string'),
  createdDate: DS.attr('date'),
  chapters: DS.hasMany('chapter', { inverse: 'book', async: true}),
  bookAssignments: DS.hasMany('bookAssignment', {async: true}),
  user: DS.belongsTo('user', { inverse: 'books', async: true} ),
});

App.Chapter = DS.Model.extend({
  name: DS.attr('string'),
  description: DS.attr('string'),
  source: DS.attr('string'),
  book: DS.belongsTo('book', { inverse: 'chapters', async: true}),
  user: DS.belongsTo('user', { inverse: 'chapters', async: true} )
});

App.User = DS.Model.extend({
  uid: DS.attr('string'),
  displayName: DS.attr('string'),
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  books: DS.hasMany('condition', { inverse: 'user', async: true}),
  chapters: DS.hasMany('statistic', { inverse: 'user', async: true}),
});

I have created a Session object that I inject into the routes and controllers

App.Session = Ember.Object.extend({
  user: null,
  userID: '',
});

Ember.Application.initializer({
  initialize: function (container, application) {
    App.register('session:main', App.Session.create(), { instantiate: false, singleton: true });
    // Add `session` object to route to check user
    App.inject('route', 'session', 'session:main');
    // Add `session` object to controller to visualize in templates
    App.inject('controller', 'session', 'session:main');
  }
});

However, the Session object is not a Model and could not be saved to the Store with the Save() method:

user.save()

Another option that I explored is to access the User record from the User Route Model Hook. The user route:

App.UserRoute = Ember.Route.extend({
  model: function() {
    //var session = this.get('session');
    var user = '';
    var _isAutheticated = this.isAutheticated;
    var store = this.store;
    var _firebase = new Firebase("https://dynamicslife.firebaseio.com");
    _firebase.onAuth(function(authData) { 
      if (authData) {
        _isAutheticated = true;
        console.log('user authenticated with Firebase', authData.uid);  
        user = store.find('user', authData.uid).then(function(_user) {
          console.log('user found', _user);
          return _user;
        }, function(error) {
        // user does not exist or some other error
        console.log('please log again');     
      });
      } else if (error) {
        _isAutheticated = false;
        console.log('failled login attempt', error);
      }
    }); //end authWithOAuthPopup
    console.log('My user2: ', user);
    //this.set('isAutheticated', _isAutheticated);
    return user;
  }
});  

I tried Needs to access the User record from the Chapter Controller:

App.ChaptersController = Ember.ArrayController.extend({ 
  needs: 'user',
  user: Ember.computed.alias("controllers.user.model"),
});

However, User remains not available.

I imaging that my syntax is not correct. I would greatly appreciate if someone could indicate me a proper way to access the User record in a way that it can be modified and saved from the Chapters controller.

The Chapters route is not nested under the User route because the templates are not nested. Should I nest the Chapters Route under the User Route even if the templates are not nested to use ModelFor()?


Solution

  • If you are trying to access a particular record from the chapter model you can do so by using this.store.find('chapter', record_id) from the controller, since store is available for all controllers (and routes).

    If you need to create a new chapter record from the controller you can do this.store.createRecord('chapter') and it will give you an empty record to work with.

    In this case there will be no need to inject the model directly.