Traversing a complex RESTful output (version 12) - ember.js

I'm getting following (simplified) output from a RESTful API:
{products: [{
product: {
id: 1, name: "T-Shirt red"
},
images: [{
id: 1, size: 'm', url: 'http://db.co/t-shirt-red_m.jpg'
}, {
id: 2, size: 'xl', url: 'http://db.co/t-shirt-red_xl.jpg'
}]
}, {
product: {
id: 2, name: "T-Shirt blue"
},
images: [{
id: 3, size: 'm', url: 'http://db.co/t-shirt-blue_m.jpg'
}, {
id: 4, size: 'xl', url: 'http://db.co/t-shirt-blue_xl.jpg'
}]
}]}
Using Ember version 12, how should the declaration of the Product model looks like and how can I traverse the results? Haven't been able to find any example in that direction.
Following to access the data doesn't work (I just can't find the right syntax):
var products = App.Product.find(); // seems to work
var prodNames = products.getEach('product.name'); // doesn't work
var secondProd = products.getObject(1).get('name'); // doesn't work
Thanks a lot in advance!
claudio.

DS.hasMany and some options for the REST adapter may help you.
I've used a similar setup with MongoDB embedded models. I've attached some examples below.
I didn't want to try to save to the embedded array, so I've used embedded:load, but you can use embedded: 'always' to persist the total object back to the server (although it didn't work quite as I expected) with 'always' if you save the parent object.
DS.RESTAdapter.map 'App.Check',
line_items: { embedded: 'load' }
parties: { embedded: 'load' }
App.Check = DS.Model.extend
description: DS.attr("string")
modified_date: DS.attr("date")
parties: DS.hasMany('App.Party')
App.Party = DS.Model.extend
name: DS.attr("string")
check: DS.belongsTo('App.Party')
You can then reference the item. In a view, I've accessed it as below from a ArrayController where the content is set to an instance of DS.Check.
{{#each party in content.parties }}

Related

Where to get product-catalog-id

I am using Facebook marketing API 3.3 version to read product feeds but I don't know where can I get the product-catalog-id.Here is the URL :
GET /v3.3/{product-catalog-id}/product_feeds
You can get your product-catalog-id in the settings page of catalog page (https://www.facebook.com/products/catalogs)
Programatically, I'm using Graph API 13.0, you can fetch your business id via:
GET me/businesses
response:
{ data: [ { id: 12345, ... }, { id: 23456, ... } ] }
Then use the business ID to fetch product catalogs:
GET ${businessId}/owned_product_catalogs
response:
{ data: [ { id: 12345, name: 'foo', ... }, { id: 23456, name: 'bar', ... } ] }
See https://developers.facebook.com/docs/marketing-api/reference/product-catalog

Loopback4 Model Definition options for mongodb collection name

I am using loopback 4 and trying to configure the Model annotation with properties to configure how the collection is created in Mongo.
I have a Model called say Client and I want the collection in Mongo to be called Clients. The cross over with documentation is confusing, as they reference the properties from v3 in v4 docs.
I have tried this:
import {Entity, model, property} from '#loopback/repository';
#model({
settings: {strict: false},
name: 'client',
plural: 'clients',
options: {
mongodb: {
collection: 'clients',
},
},
})
export class Client extends Entity {
#property({
type: 'string',
id: true,
defaultFn: 'uuidv4',
index: true,
})
id: string;
#property({
type: 'string',
required: true,
})
name: string;
#property({
type: 'string',
})
code?: string;
constructor(data?: Partial<Client>) {
super(data);
}
}
With no Joy, still creates the collection as the Class name Client
This is from 2014, but perhaps it still works. Try not putting the mongodb key options
settings: {strict: false},
name: 'client',
plural: 'clients',
mongodb: {
collection: 'clients',
},
Please note that all model settings must be nested inside settings property, LB4 does not support top-level settings yet.
Also the option plural is not used by LB4 as far as I know.
I think the following code should work for you:
#model({
name: 'client',
settings: {
strict: false
mongodb: {
collection: 'clients',
},
},
})
export class Client extends Entity {
// ...
}
UPDATE: I opened a GitHub issue to discuss how to make #model decorator easier to use for users coming from LB3. See https://github.com/strongloop/loopback-next/issues/2142

EmberJS Mirage 404 error on get /rentals

I'm following tutorial on this page (https://guides.emberjs.com/v2.7.0/tutorial/installing-addons/) until the next tutorial page. (Actually I follow until finished the tutorial.)
Everything seems to working fine. ✔
Ember server is serving and display in the browser correctly. ✔
Ember development build also display correctly. ✔
But Ember production build give me /rentals 404 error. ✖
How to fix this 404 error on production build?
Here is my mirage/config.js
export default function() {
// These comments are here to help you get started. Feel free to delete them.
/*
Config (with defaults).
Note: these only affect routes defined *after* them!
*/
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
// this.namespace = ''; // make this `api`, for example, if your API is namespaced
// this.timing = 400; // delay for each request, automatically set to 0 during testing
/*
Shorthand cheatsheet:
this.get('/posts');
this.post('/posts');
this.get('/posts/:id');
this.put('/posts/:id'); // or this.patch
this.del('/posts/:id');
http://www.ember-cli-mirage.com/docs/v0.2.x/shorthands/
*/
this.get('/rentals', function(db, request) {
let rentals = [{
type: 'rentals',
id: 1,
attributes: {
title: 'Grand Old Mansion',
owner: 'Veruca Salt',
city: 'San Francisco',
type: 'Estate',
bedrooms: 15,
image: 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Crane_estate_(5).jpg'
}
}, {
type: 'rentals',
id: 2,
attributes: {
title: 'Urban Living',
owner: 'Mike Teavee',
city: 'Seattle',
type: 'Condo',
bedrooms: 1,
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Alfonso_13_Highrise_Tegucigalpa.jpg'
}
}, {
type: 'rentals',
id: 3,
attributes: {
title: 'Downtown Charm',
owner: 'Violet Beauregarde',
city: 'Portland',
type: 'Apartment',
bedrooms: 3,
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Wheeldon_Apartment_Building_-_Portland_Oregon.jpg'
}
}];
if(request.queryParams.city !== undefined) {
let filteredRentals = rentals.filter(function(i) {
return i.attributes.city.toLowerCase().indexOf(request.queryParams.city.toLowerCase()) !== -1;
});
return { data: filteredRentals };
} else {
return { data: rentals };
}
});
}
The url prefix and namespace don't change anything, still /rentals 404 error.
GET http://localhost/rentals 404 Not Found
"NetworkError: 404 Not Found - http://localhost/rentals"
Error while processing route: index Ember Data Request GET /rentals returned a 404
ember-cli-mirage is disabled in production build, you should explicitly enable it in config:
if (environment === 'production') {
ENV['ember-cli-mirage'] = {
enabled: true
};
}
Mirage Documentation
The docs have been updated to include a fix for this issue.
Now if you go to the section in the docs called Setting up Application Tests to use Mirage you will see it says to open /tests/acceptance/list-rentals-test.js and insert in this import statements at the top:
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
Then in tests/acceptance/list-rentals-test.js and add a setupMirage(hooks); right after setupApplicationTest(hooks)
module('Acceptance | list rentals', function(hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
...
}
Then the data and the tests will pass.

Error returning promise from Ember Data

I am working on my first Ember app and got it to display the way I wanted with the route returning a static JSON object from model():
element: {
name: "First Element",
divisions: [{
name: "First Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}, {
name: "Second Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}]
}
Now I am trying to refactor to use Ember Data + Mirage and having an awful time.
Here’s my index.js route
export default Ember.Route.extend({
model() {
return this.store.find('element', 1);
},
If I set up my Mirage config.js like this:
this.get('/elements', function() {
return {
elements: [
{
id: 1,
name: 'First Element',
divisions: [1, 2]
}
]
}
});
then I get this error:
Your Ember app tried to GET '/elements/1', but there was no route defined to handle this request.
If I set up my Mirage config.js like this:
this.get('/elements/1', function() {
return {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
});
then I get this error:
22:46:40.883 "Error while processing route: index" "Assertion Failed: normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta"." "EmberError#http://localhost:4200/assets/vendor.js:25582:15
EDIT:
So this isn't a solution to the problem as stated but it got me past this. I gave up on Pretender and started again creating an actual Rails server according to this excellent tutorial: http://emberigniter.com/modern-bridge-ember-and-rails-5-with-json-api/
I was able to do everything I wanted this way and if I ever want to make this a production app, I'm a lot closer.
So the issue is that you aren't actually adhering to the JSON API specification. You can solve this by reading Mirage's page on how to conform.
Essentially you need to either be returning an object at the top level of your JSON response in the case of a GET /foo/1 call. You'll also need to change your "elements" attribute to "data" for GET /foo and that should do the trick. Right now there isn't a simple, re-usable way to do this Mirage out of the box. The best bet right now for both issues is to use the solution presented in this issue.
ember error normalizeResponse must return a valid JSON API document
can be fixed in three ways
return a valid JSONAPI response
see your error message:
normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta".
this.get('/elements/1', function() {
return {
data: {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
}
});
see also https://jsonapi.org/examples/
normalize all responses
// app/serializers/application.js
import EmberData from "ember-data";
export default EmberData.JSONAPISerializer.extend({
normalizeResponse() {
return {
data: this._super(...arguments),
};
},
//normalize(){},
//serialize(){},
// ...
});
problem: error handling
by wrapping all responses in { data: ... }, they never return errors
on errors, the response should be
this.get('/elements/1', function() {
return {
errors: [
{
id: 12345,
title: 'title for error #12345'
}
]
}
});
see also https://jsonapi.org/format/#error-objects
replace JSONAPI with REST
sed -i 's/JSONAPISerializer/RESTSerializer/g' app/serializers/*.js
sed -i 's/JSONAPIAdapter/RESTAdapter/g' app/adapters/*.js
ember docs: adapters and serializers
duplicate: How can ember application be integrated to use with json-server?

Ember observe nested array property

I want to observe a nested property. I have the following Ember Array:
specifications: [
{
title: "specification name",
filters: [
{
title: "example"
checked: false
},
{
title: "example 2",
checked: true
}
]
},
...
]
I want to create a computed property:
activeFilters: (->
Ember.computed.filterBy('specifications.#each.filters', 'checked', true),
).property('specifications.#each.filters')
The active filters property is not working, I tried several combinations of property methods, but none worked.
Is the property I am trying to create actually possible?
Yes, it is possible. The thing is that for it to work you can't use a JavaScript array, you need an Ember.ArrayProxy and then you can access its special properties: http://emberjs.com/api/classes/Ember.ArrayProxy.html
specifications: Ember.ArrayProxy.create({
content: [
{
title: "specification name",
},
]
});
So, you'll have something like:
oneSpecChangedCheck: function() {
// don't know which, but someone changed
var s = this.get('specs');
// loop and process
return s;
}.property('specs.#each.checked'),
http://emberjs.jsbin.com/zohuzo/2/edit?html,js,console,output