Badgeyay is an open source utility to develop badges for events and tech conferences. Badgeyay project is divided into two components. Frontend part is designed with ember and backend part is designed with Flask and database as PostgreSQL and Firebase as PaaS.
After refactoring the backend API for generation of badges, now it is time to consume the API in frontend by ember, and the way to consume the api in ember front–end is with the use of in built ember-data library. Ember data behaves in a way similar to server side ORM’s (Object Relational Mappers). It is a very versatile library and can be equipped with variety of backend services. It can be used with REST as well as sockets and other transfer protocols for communication.
For better understanding the working of ember data, let’s see how to use the same to consume the File Upload endpoint in the backend.
Procedure
- Enabling CORS on server, to allow cross-domain requests to the API.
from flask_cors import CORS CORS(app, resources={r"*": {"origins": "*"}})
- Creating Adapter for the model in frontend. In our case it is csv-file. In the adapter we need to specify the host and the path, because our backend api is not running on the same port.
import DS from 'ember-data'; const { RESTAdapter } = DS; export default RESTAdapter.extend({ host : 'http://localhost:5000', pathForType : () => { return 'api/upload/file'; } });
- After creating the adapter we need to create the record in the controller of the respective component. The record is like an object of a class, which when pushed to store will make a network request to backend (POST) and fetch the response from the backend. Backend response will provide the id to save in store
import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; export default Controller.extend({ routing : service('-routing'), actions : { mutateCSV(csvData) { let csv_ = this.get('store').createRecord('csv-file', { csvFile : csvData, extension : 'csv' }); csv_.save(); }, mutateText(txtData) { console.log(txtData); } } });
Model for the csv-file
import DS from 'ember-data'; const { Model, attr } = DS; export default Model.extend({ csvFile : attr('string'), extension : attr('string') });
- Next is to create serializers for the model. Serializers gets triggered at two moments, first when the data is sent to the server and second when data is received from the server. Each time an independent function gets executed. As the naming conventions of the functions pretty much explains their role, but for the sake of clarification serialize function gets executed when we send request to the server and normalizeResponse gets executed when we are getting response from the server.
import DS from 'ember-data'; const { JSONAPISerializer } = DS; export default JSONAPISerializer.extend({ serialize(snapshot, options) { let json = this._super(...arguments); json.csvFile = { 'csvFile' : json.data.attributes['csv-file'], 'extension' : json.data.attributes.extension }; delete json.data; return json; }, normalizeResponse(store, primaryModelClass, payload, id, requestType) { return payload; } });
- After receiving the response a promise is returned by the push method to save the record in the store and we can see the id is saved in the ember-data object.
Pull Request for the same is at this Link
Topics Involved
Working on the issue involve following topics:
- Enabling CORS to accept cross-domain requests at server
- Creating models in ember data
- Passing action from controller to component
- Modifying the Params and Response on the network sent by ember-data via serializers