I am looking to have additional data added onto my models after the JSON data is returned from the service. The service I talk to returns information as a code, but I want to also include a more readable name to display to users. This would be done almost everywhere the model is used.
Example:
Fetch from the service
{schedule: {code:'MONTHLY'}}
Have access to
{schedule: {code:'MONTHLY', name: 'Monthly'}}
This would be for things which have a map of code to name, where name only ever lives on the front end, and code is what is persisted. I see there is a concept of custom transforms, would this be the way to go?
I also plan to keep a mapping of all possible codes/names in another file, to iterate over or compare to the model's attributes. For instance I would want to present users with a choice of schedules to choose from, MONTHLY, QUARTERLY, or ANNUALLY.
You should create a Computed Property on a model. You can call it: "name" or "displayName". It should depend on "code" attribute on model. Inside computed property, you should access a service. Service should have a method to map code -> name. A method you call from the model on service should return you a name. A code-name map should be separated from the model.
Whenever you want to access displayName Computed Property from model use model.displayName.
Related
I would like to know if there is a way to update a ressource (product in this case), but only update fields that are specified in my request.
For example, let's say I want to update only the required fields for the product, but not change the others, how could I proceed via the webservice ?
As far as I know, when you update a ressource, it will update it as whole : This means if you don't "re-send" the original value back when updating (if you do not specify ALL the fields), it is considered as empty.
From my tests, I tried the following :
Log in my PrestaShop, get a random product, set the "width" to a random value (let's say 30 cm)
Retrieve the blank schema of a product, and fill only the required fields of the schema (width is not part of it)
Send the schema via the webservice to update the original product using a PUT request
Get back in my PrestaShop and notice in despair and sadness that the width value has been set to 0
My use case is that we have a system that is synching products with PrestaShop. When a product is edited in our system, a specific set of fields is sent back to PrestaShop so the product in the shop is also updated.
But for some of our users, they want to be able to add information on the shop and keep them even if the product is updated afterwards. For example, they add dimensions to the product (fields that are not managed / persisted in our system) and they want to keep those information.
The constraint we have is that the set of fields sent for updates is "hardcoded" : We can't get the ressource schema and update it to send it back afterwards.
Is there any parameter / configuration that can be set so values of fields that are not specified are not erased ?
Due to the nature of how the PrestaShop API works, you can perform the following:
For each product you want to update, you can pull the complete object (with all fields), then update that object with only the fields you need updated, and then push the whole object as n update for that product via the API.
Doing this for multiple products will require twice the API calls.. but this is one workaround.
One way is to use a flag variable for the properties which you want to update
I am using Django rest framework for writing some rest API in which I have two primary resources as Store and Product.
Now the URIs for these resources are like
List all the stores GET /stores/
List store with ID GET /stores/:id/
Add a new store POST /stores/
Update some attributes in a store PUT /stores/:id/
Same is applicable to products
List all the products GET /products/
List product with ID GET /products/:id/
Add a new product POST /products/
Update some attributes in a product PUT /products/:id/
Now i want to map some products to some stores like if store A is selling products with ID 1 to 100 and store B is selling products with ID 70 to 200.
With this i have got another resource as store_product_mappings
Now i can treat it as above and make URIs for this resource as
List all the store_product_mappings GET /store_product_mappings/
List store_product_mapping with ID GET /store_product_mappings/:id/
Add a new store_product_mapping POST /store_product_mappings/
Update some attributes in a store_product_mapping PUT /store_product_mappings/:id/
But now this mapping id isn't exposed to the consumers of this API. So in order to avoid this complexity i want to make a easilty understandable URI like
To list all the products inside a store GET /stores/:id/products/
To list a product inside a store GET /stores/:id/products/:product_id
To update a product inside a store PUT /stores/:id/products/:product_id
But according to this approach if i do post on this URI
POST /stores/:id/products/
It should create a new mapping resource and return the ID for that mapping resource, in the similar way it will expect the mapping id when i want to retrieve that resource back like
GET /stores/:id/products/:id
But i don't want to expose mapping ids as it's part of my internal system and consumers of API shouldn't need to worry about it. I am still looking for solutions for this kind of use case and resources in Django rest framework.
Let me know if someone has already faced the similar issue and with what approach they were able to implement this without violating the Rest API conventions.
This request:
POST /stores/:storeid/products/
can expose the product_id as part of the URI returned:
Location: /stores/{storeid}/products/{productid}
It does not need to tell you the technical id of the mapping row in your database. Remember, you don't have to expose database rows one-to-one in your REST API.
As a sidenote, if your clients are Hypertext driven (as they should be), they don't have to parse or construct URIs manually, therefore it would be not that important what you expose in the URIs.
Let's say I have two users, A and B, with IDs 1 and 2 (respectively). Further, let's assume I have two datasources configured: X and Y.
How could I isolate ALL queries issued by user A to datasource X, and all by B to Y for some given remote method? For example, say that A wants to run 'find' for some model via the API - how could I make sure that the only results A will get are those which are accessible through datasource X?
I'm not sure I entirely understand why you would decide a datasource based on the current user, but in any case, I'm not sure you can do that with LoopBack ... at least, not easily. LoopBack is a model-driven framework - everything derives from the model. As such, all API endpoints go through a model (although you can set up custom routes). And each model is connected to a single datasource.
So, if I hit /api/Widget/13 there is no way to make that findById() call switch between two datasources, it will always hit whatever datasource the model is connected to.
Okay, that all said, the solutions I see are to:
Create a "dispatcher" and have that model do the appropriate thing.
Create a custom remote method on your existing model and do the decision making there and the find, etc on the correct datasource.
In either case, it's not straightforward, and not built-in. FYI, if you need to get the datasource you can access it from the LoopBack application object: MyModel.app.datasources.ds1
So theres an route/view that only needs to show the name and id field. If and when a single model is selected then I need to re-fetch only that model (by id) but requesting more fields. With the default DS.Store, it finds the model by the id and foregoes the second full trip to the backend.
Is there an accepted method of marking a model as 'incomplete' and im not talking about this todo incomplete
The ember-data store is just a local cache of objects of data already retrieved from the server and any that have been created or updated so far by the client. The methods on the store deal with the management of this "cache" on the application level.
When you call .find() on the store it will first check that local cache, and if it has the object already there it will return that. You are probably working with a record which already exists in the store, presumably because you just created it. Ember-data doesn't do "partial" models; you load a model in its entirety.
So I think what you're looking for is the DS.Store.fetch() method: http://emberjs.com/api/data/classes/DS.Store.html#method_fetch
How do bind a DropLink using a custom dataprovider?
More info:
I am trying to build a product catalogue site using Sitecore. Each product in the sitecore content tree can have a star rating and short text review attached to it (which will be linked to a user extended with a profile provider but that is another question).
I am planning to store the review information in an external database and reference it using a custom dataprovider. I have downloaded the NorthwindDataProvider from the Shared Source (here) and have altered it to use a table which contains the rating, text and a uniqueidentifier field to store the ID of the product from in sitecore the review is attached to.
The template field is a droplink and the datasource is set to the products in the catalogue.
When I edit a review in the custom dataprovider using the sitecore content editor, the droplink states 'Value not in selection list' even if I select one of the populated products and save using sitecore.
It is saving the ID in the database but if I look at the raw value it displays the id without the curly brackets. Working droplink fields' raw values appear to contain the brackets.
To create a review, I am using a jquery post to a webservice which writes to the database using an external datacontext. Should I be using some Sitecore API to use the custom dataprovider instead?
Any information using custom dataproviders would be helpful. The documentation I've been able to find has all stated what can be done but I'm struggling to find actual implementation.
So the first thing is that you have a template field and you're using droplink which is going to store the guid for the item selected. I'm not quite clear on whether or not you're pointing the datasource to a Sitecore item or not.. but that's essential if you're using droplink. Here's what I would suggest instead for the most straight forward way to do this:
Create a template that you add fields to handle the logic dealing with your catalog items. How you do that is your choice and Sitecore doesn't care since its only going to deal with the item and all it cares about is finding an item... you write business logic to manipulate the external data.
Once you have a folder that stores your catalog items, you could easily write a script to be triggered by the Rules engine in Sitecore or a Sitecore task that runs regularly to get your catalog items to add/update or remove the corresponding list of Sitecore items.
Also, another option that is more complex to implement, but if you have multiple data sources on your site, is a valid approach, is to use an object framework (like the Entity framework) as a data object layer that allows you to create and populate common objects with from any data source.
Hope this is helpful!