Data wont render solution #212

Closed
shkherad opened this Issue Aug 1, 2016 · 8 comments

Projects

None yet

3 participants

@shkherad
shkherad commented Aug 1, 2016

Page would not render data for profile.

Routes were set up correctly but this was the model:

export default DS.Model.extend({
  given_name: DS.attr('string'),
  user_id: DS.belongsTo('user'),
  level: DS.attr('integer'),
  favorites: DS.hasMany('favorite'),
  schedules: DS.hasMany('schedule'),
});

Errors Thrown:

vendor.js:42222 TypeError: Cannot read property 'some' of undefined
message: "No model was found for 'favorite'", name: "Error"…}
message: "Assertion Failed: Unable to find transform for 'integer'", name: "Error"…}

Solution Part 1:
You can't insert into a model a property DS.hasMany if that property does not yet have a model defined somewhere in your ember client.

Solution Part 2;
DS.attr('number')
Not integer.

@shkherad
shkherad commented Aug 1, 2016

^ See solution above.
Thanks @payne-chris-r

@shkherad shkherad closed this Aug 1, 2016
@shkherad
shkherad commented Aug 2, 2016

So I created the model, and it still throws the error that the model doesnt exist.

This is my profile model:

export default DS.Model.extend({
  given_name: DS.attr('string'),
  user_id: DS.belongsTo('user'),
  level: DS.attr('number'),
  favorites: DS.hasMany('favorites'),
  // schedules: DS.hasMany('schedule'),
});

And this is my favorite model:

export default DS.Model.extend({
  profile_id: DS.belongsTo('profile'),
  recipe_id: DS.belongsTo('recipe')
});

The error is:
message: "No model was found for 'favorite'

I've tried playing around with the pluralizations: making a model for "favorites", saying profile has many "favorite" singular. Am I just messing up the pluralizations or am I linking these relationships incorrectly?

@shkherad shkherad reopened this Aug 2, 2016
@shkherad
shkherad commented Aug 2, 2016

Trying to follow this guid as directed from older closed solutions but what exactly are the inverses>

https://guides.emberjs.com/v2.5.0/models/relationships/

When I follow the guide, I get an errror that say it cant find my inverses

@berziiii
berziiii commented Aug 2, 2016

If favorites is a join table, you may need to have

profile_id: DS.belongsTo('profile', {
inverse: 'favorites'}),
recipe_id:DS.belongsTo('recipe, {
inverse: 'favorites'})

Also, check to make sure in your API you have those Inversei set in your favorites model.

Let me know if his changes anything.

@berziiii
berziiii commented Aug 2, 2016

Then through this favorites join, you should be able to call profiles from recipes and the other way around without having to reference the join table.

@shkherad
shkherad commented Aug 2, 2016

^I did that last night and got:
ReferenceError: favorites is not defined(…)
That's when I had a favorite model defined.

So i made a "favorites" (plural) model and got the same error.

I tried every combination of singular in my profile model, and even when I make both of them "favorite" (singular) it still says "favorites undefined" in the plural.

I have the inverses labeled in my backend as:

class Favorite < ActiveRecord::Base
  belongs_to :profile, foreign_key: :profile_id, inverse_of: :favorites, dependent: :destroy
end

and

class Profile < ActiveRecord::Base
  belongs_to :user, foreign_key: :user_id
  has_many :favorites, inverse_of: :profile
  has_many :schedules, inverse_of: :profile
end

@jrhorn424
Member

For serializing relationships out of the backend, you'll want to look at listr-api serializers.

You don't want to use _id on key names on the front end. Our adapters and serializers take care of that for you in Ember. Last time I did use _id I'm pretty sure I had issues loading child model instances from parents.

export default DS.Model.extend({
  given_name: DS.attr('string'),
-  user_id: DS.belongsTo('user'),
+  user: DS.belongsTo('user'),
  level: DS.attr('number'),
  favorites: DS.hasMany('favorites'),
  // schedules: DS.hasMany('schedule'),
});
export default DS.Model.extend({
-  profile_id: DS.belongsTo('profile'),
+  profile: DS.belongsTo('profile'),
-  recipe_id: DS.belongsTo('recipe')
+  recipe_id: DS.belongsTo('recipe'),
});
@berziiii berziiii was assigned by jrhorn424 Aug 2, 2016
@shkherad
shkherad commented Aug 2, 2016 edited

SOLUTION:

I got favorites to work and this solution is going to walk through how to do it for a similar join table that I have called "schedules" which also joins a profile to a recipe.

Moral of the issue: Ember works like an angel if you give it what it wants from the backend, and you run into a bit of trouble if you give it more than it wants. (Hence the importance of the pluck(:id)

BACKEND:

PROFILE MODEL:

class Profile < ActiveRecord::Base
  belongs_to :user, foreign_key: :user_id
  has_many :favorites
  has_many :recipes, through: :favorites

  has_many :schedules
  has_many :recipes, through: :schedules

end

Schedules Model:

class Schedule < ActiveRecord::Base
  belongs_to :profile, foreign_key: :profile_id, inverse_of: :schedules, dependent: :destroy
  belongs_to :recipe, foreign_key: :recipe_id, inverse_of: :schedules, dependent: :destroy
end

Recipes Model:

class Recipe < ActiveRecord::Base
  has_many :tags, inverse_of: :recipe
  has_many :ratings, inverse_of: :recipe
  has_many :profiles, through: :favorites
  has_many :favorites

  has_many :profiles, through: :schedules
  has_many :schedules
end

Profile Serializer:

class ProfileSerializer < ActiveModel::Serializer
  attributes :id, :given_name, :level, :user_id, :favorites, :schedules, :recipes

  def favorites
    object.favorites.pluck(:id)
  end

  def schedules
    object.schedules.pluck(:id)
  end

  def recipes
    object.recipes.pluck(:id)
  end

end

Schedule Serializer:

class ScheduleSerializer < ActiveModel::Serializer
  attributes :id, :eat_on, :profile_id, :recipe_id, :recipe, :profile

  def recipe
    object.recipe.id
  end

  def profile
    object.profile.id
  end
end

Recipe Serializer:

class RecipeSerializer < ActiveModel::Serializer
  attributes :id, :title, :directions, :time, :image, :ingredients, :level, :tags, :ratings, :favorites, :profiles

def favorites
  object.favorites.pluck(:id)
end

def schedules
  object.schedules.pluck(:id)
end

def profiles
  object.profiles.pluck(:id)
end


end

FRONT END:

Schedule Model:

import DS from 'ember-data';
import { belongsTo } from 'ember-data/relationships';

export default DS.Model.extend({
  profile: DS.belongsTo('profile', { inverse: 'schedules' }),
  recipe: DS.belongsTo('recipe', { inverse: 'schedules' }),
});

[the routes for schedule are the normal findAll for plural and findRecord for singular]

Profile Model:

import DS from 'ember-data';
import { hasMany } from 'ember-data/relationships';
import { belongsTo } from 'ember-data/relationships';

export default DS.Model.extend({
  given_name: DS.attr('string'),
  user: DS.belongsTo('user'),
  level: DS.attr('number'),
  recipes: DS.hasMany('recipe')
});

Recipe Model:

import DS from 'ember-data';
import { hasMany } from 'ember-data/relationships';

export default DS.Model.extend({
  title: DS.attr('string'),
  directions: DS.attr(),
  time: DS.attr('number'),
  image: DS.attr('string'),
  ingredients: DS.attr(),
  profiles: DS.hasMany('profile')
});
@shkherad shkherad closed this Aug 2, 2016
@berziiii berziiii was unassigned by jrhorn424 Aug 2, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment