I'm having issues accessing the current route params within an adapter. I've tried looking in the store and type objects that are passed in but have not been able to find anything.
I know I could use window.href.location to access the string of the url and do some manipulation to access the route param, however I'm not comfortable hardcoding that in because the url may change.
I would recommend you to use query argument passed to a method you use to query your data.
Look at the default implementation of rest-adapter's queryRecord():
query(store, type, query) {
var url = this.buildURL(type.modelName, null, null, 'query', query);
if (this.sortQueryParams) {
query = this.sortQueryParams(query);
}
return this.ajax(url, 'GET', { data: query });
},
It has access to the query argument and uses buildURL, you can override function buildURL() or query() and adjust it the way you need.
What you need to do afterwards is to use your route or controller to read query parameters from the url and pass to the store your query object to reflect your need.
Here is the link to Ember-Data DS.Adapter API
Related
As u already know the Local resolvers are deprecated so we can't use it as a perspective way to handling REST cache. What we should use instead of resolvers?
'field policies' are not good for that at all. Let's imagine... You have two different client queries: getBooks and getBook. Each query getting data from the rest API. Somehow we need to handle the situation when we already got the data from getBooks and runing another query getBook. getBook should not make a request because the data were already cached. We did that in resolvers before it was deprecated. We were just checking the cache and return the data if it already exists in the cache if not did a request. How we can handle this in current circumstances?
Sorry but it's a bit not what I meant. Here is a code example:
export const getBooks = gql`
query getBooks () {
getBooks ()
#rest(
type: "Book"
path: "books"
endpoint: "v1"
) {
id
title
author
}
}
`
export const getBook = gql`
query getBook ($id: Int!) {
getBook (id: $id)
#rest(
type: "Book"
path: "book/{args.id}"
endpoint: "v1"
) {
id
title
author
}
}
`
So we have two different queries. The goal is when we run both in turn the getBook should not make a REST request because we already have the same data in the cache since we get it from getBooks. Before resolvers were deprecated we handle it in resolvers. Like: if this ID is not exist in the cache just make a request if exist give me data from the cache. How we can do that now?
As u can see fetchPolicy it's completely different.
Local fields it's also not good because it's something about fields not about the whole entity.
I have a lambda, written in Java, that accepts a Request Object of the structure
{
"id": "be1c320a-144f-464d-b32c-38ec7fb4445b",
"userId": "foobar"
}
When I call this Lambda through the test interface with such an object, it works fine.
I want to create an API where a GET request to
/users/foobar/items/be1c320a-144f-464d-b32c-38ec7fb4445b
i.e. of the form
/users/{userId}/items/{id}
calls this Lambda.
I have created the API resources /users, {userId}, items, and {id} appropriately.
And I have created the GET method (on /users/{userId}/items/{id})and associated it to the lambda.
When I test the API, it invokes the lambda, but with null values in the request. I can see it package the path as {"id":"be1c320a-144f-464d-b32c-38ec7fb4445b","userId": "foobar"} in the logs, but that's not being sent in the body.
I have tried creating a template map (and have tried RTFM), but cannot see how to map path parameters to a body.
How do I achieve this mapping?
I think your Request Object structure may not be properly configured. There may be a few ways to configure this. Here is some information that has helped me.
How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway - Demonstrates this mapping (albeit with python). However, taking the top response, if you enable "Use Lambda Proxy integration", you can similarily do this with Java as so:
#Override
public Object handleRequest(APIGatewayProxyRequestEvent input, Context context) {
Map<String, String> pathParameters = input.getPathParameters();
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
// Handle rest of request..
}
This is a tuturial using the serverless framework to create an Api with Java. This tutorial similarily accesses the pathParameters by parsing the input rather than using the APIGatewayProxyRequestEvent java class.
#Override
public Object handleRequest(Map<String, Object> input, Context context) {
try {
// get the 'pathParameters' from input
Map<String,String> pathParameters = (Map<String,String>)input.get("pathParameters");
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
} catch (Exception ex) {
logger.error("Error in retrieving product: " + ex);
}
}
Use a mapping template.
First, in the Method Request section, you should see userId and id as Request Paths
Then, in the Integration Request, do not choose Proxy Integration.
Then in the Mapping Templates section, add a new mapping template for application/json of the form
{
"id" : "$method.request.path.id",
"userId" : "$method.request.path.user_id"
}
My api endpoint is like as follows for a model definition product.js
api/products/9720?id_shop=1&id_lang=1
I need to access the id_shop in product.js to apply a where clause before it fetches the records from products table.
Product.observe('access', function (ctx, next) {
next();
});
How would I access id_shop and id_lang?
You can use a remote method to create a custom endpoint:
https://docs.strongloop.com/display/public/LB/Remote+methods
If you really want to alter the default behavior of Model.find(), you can use loopback.getCurrentContext() and then inject the filter for every GET request:
Product.on('dataSourceAttached', function(obj){
var find = Product.find;
Product.find = function(filter, cb) {
var id_shop = loopback.getCurrentContext().active.http.req.query.id_shop;
filter = {where:{id_shop: id_shop}};
return find.apply(this, arguments);
};
});
This would overwrite any filter passed in, so you would need to handle that with additional logic.
I have an Ember app with a login form which returns the current user in JSON format after successful login.
Using createRecord sets the returned JSON attributes directly on the model. For instance, is_private becomes user.is_private, not user.get('isPrivate')?
How do I load the user model so that the attributes are set correctly and I don't have to re-fetch it using the id?
As of a few days ago in ember data 1.0 beta you can use pushPayload to load data directly into the store. For example if you get data pushed to your app through WebSockets (we use the Heroku add-on Pusher). You can call it on the store (source) directly and it will pass it through the appropriate serializer:
var postsJSON = {
posts: [
{id: 1, post_title: "Great post"}
]
}
this.store.pushPayload('post',postsJSON)
NOTE that it will not currently load a singular object (ie post: {id: 1, post_title:"First!"}) - you need to format it as plural with an array.
DS.RESTSerializer has pushPayload as well (source), in which case you need to pass it the store instead.
I highly encourage reading the source code before using, as it looks like the implementation of it will be revisited.
Supposedly, the official way to do this is using adapter.load, as described in this thread:
Loading Data
Previously, some features of the store, such as load(), assumed a
single adapter.
If you want to load data from your backend without the application
asking for it (for example, through a WebSockets stream), use this
API:
store.adapterForType(App.Person).load(store, App.Person, payload);
This API will also handle sideloaded and embedded data. We plan to add
a more convenient version of this API in the future.
But unfortunately, it doesn't handle sideloaded data, despite what the documentation claims. I personally use something like the following, which is based on how find(ID) is implemented:
var id = json["person"]["id"];
var store = DS.get("defaultStore");
var adapter = store.adapterForType(App.Person);
adapter.didFindRecord(store, App.Person, json, id);
var person = App.Person.find(id);
Note that this code assumes JSON in the same format that find(ID) expects to receive from the server, as documented in the RESTAdapter guide:
{
person: {
id: 1,
is_private: false,
projects: [3]
},
projects: [
{ id: 3, name: "FooReader" }
]
}
This will apply any transformations you've configured using keyForAttributeName (such as mapping is_private to isPrivate), and it will handle sideloaded records. I'm not sure if this is a best practice, but it works quite well.
how about store.push('user', userJSON)?
http://emberjs.com/guides/models/pushing-records-into-the-store/#toc_pushing-records
All answers above did not work for me.
What only worked for me was:
this.store.buildRecord(this.store.modelFor('person'), data.id, data)
e.g.
FB.api('/me/permissions="user_photos"', function (response) { });
instead of
FB.api({ method: 'fql.query', query: 'SELECT user_photos FROM permissions WHERE uid=me()' }, function(resp) {
for(var key in resp[0]) {
if(resp[0][key] === "1")
console.log(key+' is granted')
else
console.log(key+' is not granted')
}
});
Yes, Theres a way called selection in graph api or more advance field expansion:
You can choose the fields (or connections) you want returned with the "fields" query parameter, Example:
FB.api('/me/permissions?fields=user_photos', function (response) { });
Graph API Explorer Demo
EDIT:
Quoted directly from graph api doc:
Selection
By default, most object properties are returned when you make a query.
You can choose the fields (or connections) you want returned with the
"fields" query parameter. For example, this URL will only return the
id, name, and picture of Ben:
https://graph.facebook.com/bgolub?fields=id,name,picture
You can also request multiple objects in a single query using the
"ids" query parameter. For example, the URL
https://graph.facebook.com?ids=arjun,vernal returns both profiles in
the same response.
The "ids" query parameter also accepts URLs. This is useful for
finding IDs of URLs in the Open Graph. For example:
https://graph.facebook.com/?ids=http://www.imdb.com/title/tt0117500/
Additionally, there is a special identifier me which refers to the
current user. So the URL https://graph.facebook.com/me returns the
active user's profile.
When retrieving Posts via the /home, /feed, or /posts connection, you
can restrict the results to only those with a location attached by
adding with=location to the URL parameters:
https://graph.facebook.com/me/home?with=location
Source: Graph API Docs