Challenges of performance in EmberJS and Rails 4 API

My EmberJS application is connected to a Rails 4 REST API. While the application is generally working fine, it has started to slow down due to the nature of the queries being made.

Currently, the API response looks like this:

"projects": [{
    "id": 1,
    "builds": [1, 2, 3, 4]
}]

The issue arises when a user has numerous projects with multiple builds within them. EmberJS currently fetches the builds key and then sends a request to /builds?ids[]=1&ids[]=2, which is the behavior I want.

This dilemma can be solved in one of two ways.

  1. Enhance Rails to load the build_ids more efficiently
  2. Upgrade EmberJS to accommodate different queries for builds

Option 1: Enhance Rails

I have attempted various solutions related to eager loading and manually extracting IDs using custom methods on the serializer. However, both of these methods involve adding excessive code that I prefer to avoid and still result in individual queries per project.

By default, Rails also performs SELECT * style queries when dealing with has_many associations, and I am unsure how to override this at the serializer level. I also tried a messy solution that consolidated everything into a single fast query by using raw SQL, but I understand that such an approach goes against the Rails convention and would lead to a complex untestable query as the default scope, which is not ideal.

Option 2: Modify EmberJS Queries

Instead of fetching /builds?ids[]=1&ids[]=2, I prefer not to include the builds key in the project object altogether and make a request to /builds?project_id=1 when accessed in Ember. I believe I can achieve this manually on a field-by-field basis by utilizing something similar to the following:

builds: function () {
    return this.store.find('builds', { project_id: this.get('id') });
}.property()

as opposed to the current:

builds: DS.hasMany('build', { async: true })

It is also important to note that this issue extends beyond just "builds". There are four other keys in the project object that exhibit the same behavior, resulting in four queries per project.

Answer №1

Ensure that your database has the necessary indexes configured correctly. Specifically, adding an index to the builds table on project_id will significantly improve performance.

Another option is to utilize the links attribute for loading your records.

{"projects": [{
    "id": 1,
    "links": {
      "builds": "/projects/1/builds"
    }
}]}

By doing this, the builds table will only be queried when the relationship is accessed.

Answer №2

Here are some suggestions to optimize your Rails application:

  • Make sure to select only the necessary columns in your rails controller for JSON serialization.

  • Ensure that you have indexes on columns used in where and join clauses, especially foreign key columns.

  • Be cautious when using ActiveRecord's joins, includes, preload, eager, and references methods as they can impact queries issued and results returned.

  • Consider benchmarking and using EXPLAIN to determine the most efficient way to reduce SQL queries, whether through joining tables or sub-queries.

  • Opt for querying by parent_id if it simplifies database requests, particularly with Ember Data.

  • Explore using Ember-Model instead of Ember-Data for simplicity and multi-fetch support.

  • Utilize embedded or side-loaded models to minimize web requests and SQL queries.

  • Avoid 1+N pattern in SQL queries by leveraging AR's includes options for eager loading.

  • Consider alternatives like Sequel and ToJson for improved query performance compared to ActiveRecord and JBuilder.

Switching to Sequel and ToJson can drastically enhance request serving capacity and query performance in your Rails application, providing significant improvements in speed and resource management.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Display just the minutes using react-countdown-circle-timer in a React application

Looking to create a test page in React featuring a countdown timer set at 50 minutes, I integrated the react-countdown-circle-timer module. However, I encountered an issue where the minutes displayed do not change dynamically as they should. My goal is to ...

Access JSON value using jQuery by key

Creating a JSON structure that contains information about attendees: { "attendees": [ { "datum": "Tue, 11 Apr 2017 00:00:00 GMT", "name": " Muylaert-Geleir", "prename": "Alexander" }, { "datum": "Wed, 12 Apr 2017 ...

Having trouble with Angular 2 and localhost/null error while attempting to make an http.get request?

In my Angular 2 webpage, I am using the OnInit function to execute a method that looks like this (with generic names used): getAllObjects(): Promise<object[]>{ return this.http.get(this.getAllObjectsUrl).toPromise().then(response => response. ...

express-locale: locales property not functioning as intended

I've been experimenting with using express-locale (v1.0.5) as middleware in my express app to identify the locale based on the browser request. My goal is to compare the identified locale with a list of 'allowed' locales and use a default i ...

Refreshing SQL Server data using an HTML form

In the table below: <table id="skuTable" role="grid"> <thead> <th class="skuRow">Order</th> <th>Fab. Date</th> <th class="skuRow">Norder</th> <th>Color</th> ...

What are the steps to implement email validation, Saudi mobile number validation, and national ID validation in cshtml?

Looking to implement validations for the following fields: email, mobile number (must be 10 numbers and start with 05), and National ID (must be 10 numbers and start with 1 or 2) <input class="form-control" type="text" id="txt ...

Firebase authentication encountered an error due to a network request failure

Utilizing firebase Hosting to host my website, I am encountering a persistent error when attempting to login using email/password. This is the JavaScript code that I am using: window.onload = () => initApp(); //Initialize screen function initApp(){ ...

Tips for incorporating user access control logic into a lazy-loaded Angular Monorepo application without embedding the logic in the main application

In our current project, we are developing an Angular application utilizing the Angular monorepo structure. This setup includes a parent application and several children applications, with the parent application located in the `app` folder and the children ...

Tips for hiding the overflow scrollbar on Microsoft Chrome when there is no content to scroll

Looking for a solution to hide scroll bars in Microsoft Chrome, but only when there is no content to scroll? The current div and styles always show the horizontal and vertical scroll bars, even when the height exceeds the content. <div style="backgroun ...

Tips for activating multiple CSS animations when scrolling

I am currently working on a project that involves multiple CSS animations. However, I am facing an issue where these animations only occur once when the page initially loads. I would like them to trigger every time the user scrolls past them, regardless of ...

Retrieve the content of a file and convert it into JSON or GeoJSON format

Can someone help me with my issue? I am struggling to extract content from geojson files and assign it to a valid variable. Here is what I've tested: //this works var obj_valid = {"type": "FeatureCollection","crs": { "type": "name", "properties": { ...

Display function not functioning properly following AJAX request

I'm working on a functionality where I want to initially hide a table when the page loads, and then display it with the results when a form is submitted using Ajax. The issue I'm facing is that the code refreshes the page and sets the table back ...

Troubleshooting: Node.js not receiving data from HTML form

I am currently facing an issue with my HTML form and Node.js server. Despite implementing a form that is supposed to send data to the server, no information is being transferred. The form successfully makes a request, but it fails to send any form data alo ...

Install the npm package if there have been modifications to the package.json file

In short: Can we make npm install run automatically before executing any npm script if the package.json file has been modified? Situation Summary Imagine you switch to a branch that has updated the package.json file. You try running npm run my-script, bu ...

How to retrieve the path, route, or namespace of the current or parent component/view in a Vue.js application

I have been working on enhancing a sub-menu system for vue.js that dynamically populates based on the children routes of the current route. I recently asked a question about this and received a helpful answer. Currently, I am trying to further improve the ...

Utilizing the power of Vue.js version 2.x alongside the sleek features of Bootstrap

I'm currently experimenting with incorporating Bootstrap 5 into Vue (2.x) without relying on any third-party libraries. My approach involves creating a custom wrapper for select Bootstrap components that I intend to utilize. For guidance, I've b ...

What could be causing the issue with Collection.find() not functioning correctly on my Meteor client?

Despite ensuring the correct creation of my collection, publishing the data, subscribing to the right publication, and verifying that the data was appearing in the Mongo Shell, I encountered an issue where the following line of code failed to return any re ...

Positioning a div on the right side of its parent div

Hi there! I'm currently working on a small navbar that has two sections: the left section with an arrow icon and the right section with two icons - an envelope and an exclamation triangle. I've been trying to position the right section in the top ...

Is there a method to store only a portion of the string object in async-storage?

Is there a way to save only part of the string object into async-storage? For example, if the "result.userPrincipalName" contains "[email protected]", I want to save only the "bob23". What is the best method to achieve this? await AsyncStorage.setIt ...

Cypress and Cucumber collaborate to reinitialize the requests within Next Js

In my upcoming project with Next.js, I am utilizing Cypress for testing a specific page. The objective is to validate two scenarios: 1. Successful outcome and 2. Error handling when a user encounters an issue. Before(() => { return void cy.server() ...