Rails are built on the MVC architecture. It is important to maintain a thin controller to increase the readability and testing of code.
You can use the index method to extract a list of red and yellow shirts.
"{class ShirtsController < ApplicationController
def index
@white_shirts = Shirt.where(color: 'White')
@red_shirts = Shirt.where(colour: 'Red')
end}"
Now, transferring this code to the database called "Shirt model" to extract the red and white, we hope you can see how much simpler it is to construct the controller's index method.
This will help to specify these searches even more precisely.
"{class Shirt < ActiveRecord::Base
scope :color, -> (option){ where(color: option) }
end
class ShirtsController < ApplicationController
def index
@white_shirts = Shirt.color('white')
@red_shirts = Shirt.color('red')
end}"
When you encounter Database queries in the controller method, always use the second approach. There are many ways to use logic, but we recommend using the following best practices in the controller.
ERB allows you to embed ruby within HTML. You need to be careful when building your views. Large-view files can be difficult to maintain and manage.
It is possible to get into code repetition in this area, which can lead to DRY (don't duplicate yourself) violations.
Some recommended best practices of Rails:
Active Record models are not responsible for all functionality. For example, generating email notifications and interacting with external services.
Active Record's core functionality is to perform CRUD in a database.
The model has some very powerful logic:
We have literally been saying we don't use logic anywhere in MVC. You may stop and think about where we can use our logic.
Did they say no to logic anywhere on the rails? Evidently not! You can use logic inside MVC, but it is not recommended. Instead, you can use all logic outside of MVC, which won't affect the performance of your application and is also easy to manage with responsible programmer Ruby on rails.
Remember that the gems you add to your Rails application can have dependencies. Gems, in turn, may depend on other gems.
Rails applications that have more gems will be larger than they need to be. This can slow down application performance. It may also lead to increased server memory configurations and higher operating costs.
Did you know that by adding the gem "rails_admin" to your application, 11 additional gems will be added? These 11 additional gems could have more dependent gems, and so on.
Always be sure to cross-check and double-check when adding gems to your application.
It is important to keep an eye on your log files during the testing and development of your application. You will run into N+1 query problems often.
Reviewing your log files is the only way to find out what the problem is. It is easy to identify inefficiencies by reviewing log files.
At least one high-level test case should be written for every action in your controller. This testing development framework can be used to verify the basic functionality of an application if it is ever extended, modified, or upgraded into a new ROR version.
By writing test cases, you may find defects in your logic.
We have been integrating third-party services in our applications using gems that call their APIs. But we can't guarantee it will run smoothly.
What if the service becomes very slow? You can avoid blocking calls by making them background tasks instead of calling the services directly as a request.
These are the most popular gemstones for this purpose:
Rails default to the ERB Templating System, allowing you to embed Ruby code within HTML. Always use Slim or HAML templates if possible, as they are lighter than ERB.
The syntax of Slim or HAML is much easier than ERB. Slim is a lightweight, fast-templating engine. This will help you to achieve cleaner code, greater readability and reduced response times.
This also makes it possible to create your front end quickly.
Bullet - A powerful gem that increases the performance of your application. It displays an alert message in your browser when identifying N+1 query problems.
Rails Best Practices - It provides suggestions and checks the code quality.
Deadweight - It identifies CSS selectors that are not used.
This will speed up the retrieval of data from the database.
This will have a significant impact on the performance of your app.
Rails create, by default, a helper for each controller.
Use aspect-oriented helpers such as form helper and links helper.
Discover our Unique Services - A Game Changer for Your Business!
This is something that every experienced Rails developer knows or find ruby on rails developers, but it's still worth mentioning.
Used to query a list that spans multiple tables. Product. Map product.brand.name, for example, gets a list with brand names that would generate SQL statements equal to the number of products in the database.
Simply modify it to Product to avoid this. Rails would eagerly load the list of brands first if you included (: brand) in your code. Although the initial query is heavier, you should avoid using multiple SQL statements if you can get the information you need simultaneously.
You can use the bullet gem to find these nasty optimization leaks. We highly recommend using this gem to detect these issues early in any Rails project.
As with the previous tip, avoid looping multiple SQL statements to create and update records. We had a case where we needed to insert or modify thousands of records each minute, and looping was painful.
Rails 6 now supports bulk inserts using three methods: Insert_all and Insert_all, Upsert_all. You can use the ActiveRecord import gem if you are using an older Rails version.
It is important to know the differences between the most common Ruby methods, even though they will not make or break the application in most cases.
Rails are constantly changing its behavior, which causes confusion among Rails developers. Rails 5.1 has stabilized the situation.
Present vs Exists and Any
Rule Of Thumb
It can be used if you know when to use it.? For newer Rails versions, and is recommended.
Blank? Empty?
Rule Of Thumb
.empty? is available for newer versions.
Count vs Size vs Length
Has a similar behavior?
It will use a COUNT if the array is already loaded.
Rule Of Thumb
Note: Because size and duration always generate SQL queries, the results may not be identical. It's best to double-check!
Puma is Rails' default web server. Puma is configured to run on a single worker and use threads for multiple requests.
Puma can be tuned to run in clustered modes with multiple threads and workers. Do some load testing in a production environment to find the optimal number of threads and workers.
While this is a great starting point, it should not be a rule. You can increase the number of CPU cores to four or five times and still see a significant performance gain.
However, this would increase your CPU or RAM, so be sure to check it out during load testing. Rails apps are notorious for consuming a lot of memory, so be sure not to run out of that to hire dedicated ruby on rails developer.
No one-size-fits-all solution exists, but you should aim for at least three workers per container or server with 3 to five threads.
Consider moving to a stronger instance or dyno if you cannot have 3 workers due to CPU or memory limitations. Listen to Nate Berkopec's great talk on tuning your web server configuration. Consider also checking out Puma v5's experimental features! We had great success in using the wait_for_less_busy_worker and the nakoyoshi_fork for programmer productivity.
We would stay away from using the still popular active_model_serializer gem. Use the fast_json_api (originally developed by Netflix) serializer or something similar.
Use the oj jewel, which provides faster json handling. This can be a big help when processing large quantities of JSON programmer productivity.
If you are using AWS, point your Route53 record at a CloudFront Distribution in front of your Application Load Balancing (ALB).
Cloudfront will then optimize traffic to your application to go through the closest edge location of code within the AWS global networks. An edge location of code is likely much closer to the end user than the ALB. You may experience different results, but ours improved 80-100ms in latency by simply pointing Cloudfront to the ALB.
Note that we have not implemented any sort of caching essential components in the programming language.
Be sure to customize Cloudfront to point at your application's errors page before doing this. Cloudfront's error page should not be ugly.
You don't want your customers to see it. You can also configure AWS WAF to protect your app from malicious attacks on the programming ruby.
You can cache your http data through the CDN once you've configured a CDN to be in front of ALB. It will be very fast since all data is cached on the edge.
This is not an easy setup. There are many factors to take into consideration. You can cause yourself headaches by accidentally catching the wrong items.
It can be rewarding, but proceed cautiously.
Rails cache files by default. This isn't the best option if you're running a production website with multiple web servers, each with its own cache stores.
Rails now support caching using Redis. Redis caches the data in memory, which makes any app load much faster. Your site can serve thousands of users without purchasing additional CPU or memory.
Consider using the hired Gem to load Redis cached content faster. ElastiCache can also be used in production to ease the management of your Redis cluster.
We would advise you to avoid hard deletions. Hard deletes remove the row completely from the database and are final.
You cannot "undo" anything unless you have backups. In general terms, it would be useful to know when records have been deleted. The popular "discard gem" adds an elegant way to soft deletes.
Pagy consumes more memory than other popular pager gems like Kaminari or will_paginate. Pagy, the new kid in town, is more efficient.
Set MALLOC_ARENA_MAX=2, and see if your app's memory consumption improves. We were surprised at how this relatively small change reduced our app's memory footprint by around 10%.
Try running ruby with jemmaloc to reduce memory usage. We have not personally used jemmaloc to run Ruby, but several articles recommend it.
SQL is a fundamental part of Rails development. ActiveRecord is a simple abstraction over SQL. ActiveRecord is a better alternative to Ruby's .map and .select.
SQL is designed to filter and query data, so it's faster and more efficient. Use the right tool to do the job.
# Bad orders.select order.state == pending # Good orders.where (state: pending)
For complex queries, you may have no choice but to use raw SQL by using ActiveRecord.connection.execute(sql_string).
ActiveRecord is still the best option, even though raw SQL will be faster. Maintaining long lines of SQL can become unbearable over time. Use raw SQL only when ActiveRecord prevents you from completing the task.
When adding indexes, always add a code>disable_ddl_transaction!/code> along with code>algorithm: concurrently/code> to prevent any unexpected downtimes when deploying to production.
Also, when adding indexes, always add a disable_ddl_transaction! Together with the algorithm: concurrently prevent any unexpected downtimes when deploying to production. The topic is long, so check out the guidelines for the strong_migrations jewel. We don't normally put the gem into my app, but it is helpful to learn about the general guidelines to achieve zero-downtime migrations.
You should always index your foreign keys. The lol_dba jewel can be used to determine if indexes are missing. Be familiar with index types other than B-Tree.
We have primarily used Postgres, but we think it would be similar to other SQL engines. Here's a quick walkthrough:
Indexes With Multiple Columns:
Postgres is able to combine two indexes, so performance can vary.
The Postgres documentation states:
Suppose your workload is a mixture of queries involving columns x and y and sometimes only the x column. In that case, you may create separate indexes for x and y and use index combinations to process queries involving both columns.
You can also create a multicolumn (x,y) index. This index is more efficient for queries involving both columns but would be useless for queries including y. It should not be your only index.
Combining the multicolumn and a separate index for y could be a good solution. The multicolumn could be used for queries that only involve x. However, it would be slower and larger than an index containing x.
Partial Indexes:
You can enforce only one order per user by using a partial unique index if you need to.
Orders with a completed state will increase over time as orders are marked complete daily.
Our app's queries are more likely to be interested in pending orders.
A partial index is beneficial because there's a large difference between thousands of pending and millions of completed orders.
GIN Index:
While we recommend against using your database for full-text search queries, a GIN Index can be extremely helpful in certain situations.
Consider the default values for your database columns. Should it be nil? Should it be 0 or code>nil/code>? null is different from zero or an empty string.
It's probably best to specify the default value and a Not Null constraint if it does not matter. You'll save yourself some headaches in the future.
When dealing with booleans, it is best to specify a default and a not NULL constraint. No one would want three possible values in a Boolean column: true-false, and null programming experience.
ElasticSearch makes it easy to create a powerful search engine ready for production. You can manage Elasticsearch's quirks and syntax using the elasticsearch_rails jewel in conjunction with search kick.
This is another tool that you will need to manage, so it's only worth considering if your search needs are complex. Although it isn't difficult to install, this adds another layer of complexity to the app. If you want to minimize the maintenance burden, consider using a managed service such as AWS ElasticSearch for programming ruby.
You can use the popular gem ransack for a simpler search. Use this gem only for simple searches, as it relies on the database.
When you use the LIKE operators, be careful. One time, we confused the _eq predicate with _matches and wondered why our queries ran so slowly in programming ruby.
Use Postgres count estimations when you don't need a precise count. The count estimation query is fast and usually accurate enough.
Use EXPLAIN and ANALYZE to understand how your query executes its actions. Unfortunately, ActiveRecord does not have native support, but you can opt to use the ActiveRecord-explain-analyze gem.
EXPLAIN and ANALYZE results can be difficult to understand when you have complex queries. This handy tool from Depesz will help you make sense of explained statements.
You can use SQL queries to get a better idea of the state of your database. Look at the rails_pg_extras Gem for different SQL commands.
You can run a few rake tasks to get a better understanding of index_usage, outliers and locks.
Have you been using a database for many years? Do you feel that queries are getting significantly slower? Does it happen with a table that has frequent updates and deletions? Check if you have bloated tables or indexes by running rake: bloat in the rails_pg_extras jewel.
When we perform thousands of updates and deletes in our database, the bloat increases. Postgres doesn't delete the row but marks it as unavailable for all future transactions.
We are simplifying this, but the row is still on disk. It's just not visible. This would increase over time for large databases. This is the bloat that slows down your queries.
VACUUM FULL will completely remove the bloat. This command will lock your table with EXCLUSIVE LOCKS, meaning that no reading or writing can be done during the command.
Yikes. This would result in downtime for any production environment. Install pg_repack instead, which will allow you to eliminate all bloatware without having an exclusive lock.
It's over! Congratulations on reaching the end of this list in a blog post. We are certain that there are things we have not covered, but there will never be a complete list.
Please let us know if you've got any other tips! Don't be overwhelmed if you are just beginning your web development journey! You'll get there if you take things one step at a time or hire ruby on rails developers from coders.dev.
Coder.Dev is your one-stop solution for your all IT staff augmentation need.