When to Use after_commit in Rails ?

Active Record Callbacks helps us to execute code at certain stages of object life-cycle.

Let’s take a scenario, where whenever a user is created, you want to send mail to the user. So, in order to achieve this we will use after_save callback.


# app/models/user.rb

class User < ApplicationRecord

  after_save :send_email_notifications

  def send_email_notifications

    SendEmailNotifications.perform_later(self.id) # This will send email notifications in the background

  end

end

Now, this looks perfectly fine right ??

But, there is one issue with this code.

Race Condition
In the above scenario, after_save callback will be executed when the user record is saved to database. But what if commit transaction is not yet completed ?

In this case it will still send the email notification and it will raise NotFound Error while performing SendEmailNotification job.

 

So, how to overcome this?

HOW TO SOLVE THIS ?

In order to solve this, we need to use after_commit callback in place of after_save.

after_commit callback will be performed only when the actual commit transaction happens to database.

 
# app/models/user.rb 

class User < ApplicationRecord 
  after_commit :send_email_notifications, on: :create
  
  def send_email_notifications
    SendEmailNotifications.perform_later(self.id) # This will send email notifications in the background 
  end 
end 

So, we should always think before using callbacks, which one of them will satisfy our requirements and then use it.

Advertisements

Command Injection in Rails

Command Injection is a type of injection where attackers gains access to your system through your application. It occurs when a system command includes user manipulatable values.

Here are the common command lines which we generally use in rails application:

  • `….`
  • system()
  • %x[….]
  • exec()

Now, this is what command injection looks like:


path = "#{Rails.root}/public/#{params[:name]}"

`mkdir -p #{path}`

`ls #{params[:file]}`

Here, as the params data is provided by user, so it can be used by attacker to manipulate our system command and execute it.

In the above case, the attacker can just pass params[:file] value as  ; cat ./config/database.yml  and thats it. Just by doing this they have gained access to view your database credentials which is obviously sensitive.

So, how to prevent this from happening?

In order to prevent it from attack like command injection, we need to break our command into separate strings like this:

 

path = "#{Rails.root}/public/#{params[:name]}"

system("mkdir", "-p", path)

system("ls", "params[:file]")

Hope you liked it, for more such information stay tuned 🙂

Expression Indexes and Operator Classes in PostgreSQL

In this blog we are going to explore expression indexes and Operator Classes in PostgreSQL and its support in Rails. But before diving deep into it, we should be aware about terminology like Indexes.

So, moving on what is Expression Indexes ??

In order to understand that, let’s take a scenario, suppose there is a movies booking application and on one page we want to filter movies on the basis of movie name. So, what would be the query for the same ??

It will be following in:

PostgreSQL:

  SELECT * FROM movies WHERE lower(name) = 'name';

 

Rails:

  Movie.where("lower(name) = ?", name.downcase)

 

Okay, so everything looks perfect, but what if the number of movies increases?

In that case this query will take time. So, in order to optimise it we need to do indexing for this column name.  But in this case normal indexing will not work because here we are using expression lower(name) in the where clause. 

For such cases, PostgreSQL helps us by perform Indexing On Expressions

PostgreSQL(supported above  or equal to 9.4 versions) :

  CREATE UNIQUE INDEX index_movies_on_name_unique ON movies (lower(name));

 

Rails(supported Rails 5) :

  add_index :movies, "lower(name)",
            name: "index_movies_on_name_unique",
            unique: true

So, our problem is solved now right ?

Yes, regarding the above scenario, expression indexing solves our issue.

But what if on that page, we need to perform partial search on the basis of movie’s name ?

In this case, our query will look like this:

Rails:

  Movie.where("lower(name) like ?", "%#{name.downcase}%")

Here, in PostgreSQL, the indexing which we did earlier using expression indexing will not be used, instead it will go for sequential searching.

Therefore, for this we need to remove expression indexing and add operator class to the previous index, so that during searching it will use this one instead of doing sequential search

PostgreSQL(supported above  or equal to 9.4 versions) :

 CREATE UNIQUE INDEX index_movies_on_name_unique ON movies (lower(name) varchar_pattern_ops);
Rails(supported Rails 5) :
 
 def change
  remove_index :movies, name: :index_movies_on_name_unique
  add_index :movies,  'lower(name) varchar_pattern_ops',
                        name: "index_movies_on_name_unique",
                        unique: true
 end 

Hope you liked it, for more such information stay tuned …. 🙂

What is this Rack?

We as developers use frameworks like Rails, and while using it everything seems like magic to us because of abstraction. But have you ever thought of how the internal Request/Response cycle works in these frameworks Or who is the one driving it internally ?

 

HOW?

 

So, to solve everyone curiosity, RACK is the one which is responsible for handling all these things.

But what is this RACK??

What is that?

 

Rack is the middleware which helps application server to run your rails app. You can think of it as a common language that both your app server and rails application understands. So, our app server interacts to our rails application using rack(translator).

 

RACK INTERFACE

Rack defines a simple interface and it must have these three properties:

  1. It must respond to Call method
  2. Call method takes a single argument, termed as env/environment. This env contains all the data about the request
  3. Call method returns an array of three elements which is [status, headers, body] of the response

 

Lets understand this by writing a simple rack complaint application, which returns the text “Hi, I am RACK” 🙂

 
require 'rack' 
require 'thin' 

class RackApp 
 def call(env) 
  [ 200, { "Content-Type" => "text/plain" }, ["Hi, I am Rack"] ] 
 end 
end 

Rack::Handler::Thin.run RackApp.new 

In the above example we can see that RackApp is a class which has one instance method termed as
call which takes env as a argument and returns an array containing three elements:

  • Status Code: 200(HTTP “OK” status)
  • Header: Content-Type(text/plain)
  • Body: [“Hi, I am Rack”]

Here one thing to note down is that Body of the response must respond to each, thats why normal string is enclosed in an array and then returned. But in case of some type of IO object this enclosing inside array is not required.

 

Hope you liked it. In the next blog we will be covering little complex designing using Rack interface. So for more such information stay tuned …. 🙂

 

Partial Indexing In PostgreSQL

In this blog, we are going to learn about Partial unique indexing in PostgreSQL and Rails. But before that, I think you all should know about PostgreSQL Duplicate Null Values in Unique Column which I had written in my previous blog.

So, first of all what is Partial Indexing ????

According to the PostgreSQL documentation,

partial index is an index built over a subset of a table; the subset is defined by a conditional expression (called the predicate of the partial index). The index contains entries for only those table rows that satisfy the predicate.

In simple terms, it is process of adding unique index only on particular portion of database records, and that portion is defined by some condition.

So, in order to understand this, let’s take a scenario, where we have users table and we have email column, whose value must be unique. It means no two users can have same email, and we are deleting these users using soft deletion mechanism. Soft Deletion means deleting user from database will not remove it permanently from database, but will set deleted_at column value(current_timestamp). This column is used for categorizing deleted records from persisted ones.

Here, we have uniqueness constraint applied on email column, so if we delete one user with a email say “test@test.gmail”. And later if somehow we want to create user with same email, it will throw error, when we are using our conventional unique constraint. Because even though we have deleted user, it still persists in our database as it is soft deleted.

What is the solution then????

Okay at first, you all will think that creating unique index on the combination of these two columns(email, deleted_at) will solve the problem here.

  CREATE UNIQUE INDEX users_email_deleted_at_idx
  ON users (email, deleted_at);

But dear folks, this will not work.

WHY NOT????

Do you all remember this….?

PostgreSQL standard do not consider two null values as same, which I had already discussed in my previous blog.

  -> user1 = { "email": "test@test.com", deleted_at: null }
  -> user2 = { "email": "test@test.com", deleted_at: null }

Because of this, these user1 and user2 will be treated as different entity.

So, is there any solution for this ????

Yes, we have i.e our saviour “PARTIAL INDEX”

But, how will we implement partial index ?

In order to achieve this, we will add conditional index using “where” clause like mentioned below:

  CREATE UNIQUE INDEX users_email_deleted_at_null_idx
  ON users (email)
  WHERE deleted_at IS NULL;

Yayyy, now this will solve our all issues 🙂

BONUS: Also, we have active record helper for creating partial indexing in rails i.e

  add_index :users, :email, unique: true, where: "deleted_at is null"

Hope you liked my blog. For more information like this stay tuned ….. 🙂

PostgreSQL Duplicate Null Values in Unique Column

Here in this blog, I am going to tell you about some interesting behavior of PostgreSQL database. But before diving deep into it, we should be aware about terminology like Unique Constraint.

Unique Constraint is the concept that ensures that, data stored in a column is always unique, if uniqueness constraint is applied on that column . In short, Unique indexes are the way to avoid data inconsistency and duplication.

So, what is the interesting behavior ?

Consider a scenario, where we have to do unique indexing on a particular column in an already existing table. Also, we are confident that there are no duplicate values present for that column. But we are not sure about null values i.e, it may be possible that we have duplicate null values for that column.

So, what will happen if we do unique indexing on that column, which may have duplicate null values ?

Here comes the BOOM !!!

Answer is, we’ll not get any error when we’ll do unique indexing on that column.

You all must be thinking WHY ?

So, let me tell you one interesting or you can say weird behavior of  PostgreSQL……

Do you know that duplicate null values does not violate uniqueness constraint in PostgreSQL?

Exactly that was my reaction, when I came to know about it. Ideally when we insert same values twice in the column having uniqueness constraint, it should fail. But for null values it doesn’t fail.

  testname=# CREATE TABLE Demo (name varchar unique);
  CREATE TABLE

  testname=# INSERT INTO Demo (name) VALUES ('TestName');
  INSERT 0 1

  testname=# INSERT INTO Demo (name) VALUES ('TestName');
  ERROR:  duplicate key value violates unique constraint "demo_name_key"
  DETAIL:  Key (name)=(TestName) already exists.

In the above example, it is the normal behavior that inserting same value(‘TestName’) twice in the unique column(‘name’) will fail.

  testname=# INSERT INTO Demo (name) VALUES (null);
  INSERT 0 1

  testname=# INSERT INTO Demo (name) VALUES (null);
  INSERT 0 1.

But what is happening here, why it not showing error when we are inserting duplicate value(null) twice in the unique column(‘name’) ?

Yes…. Yes I know this is kind of confusing. But this is what PostgreSQL follows, SQL standards.

According to SQL standard :
“In general, a unique constraint is violated when there are two or more rows in the table where the values of all of the columns included in the constraint are equal. However, two null values are not considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior conforms to the SQL standard, but we have heard that other SQL databases may not follow this rule. So be careful when developing applications that are intended to be portable.”

For more information like this, stay tuned 🙂

Performance Tip In Ruby

Today performance is what that comes first, both from the end-user perspective and from developers point of view. So in this blog, I’ll be covering some simple things which we developers should follow, in order to optimize performance of our ruby code.

Here are the some tips with there benchmarking result:

  • Always use string interpolation instead of string concatenation
  language = "ruby"
  Benchmark.bm do |x|
    x.report {p "testing string, "<< language}
    x.report {p "testing string, #{language}"}
  end

  [#<Benchmark::Tms:0x000000000b271388 @cstime=0.0, @real=6.565399962710217e-05, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>,
   #<Benchmark::Tms:0x000000000b270b40 @cstime=0.0, @real=4.6490000386256725e-05, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>]

From the above benchmarking, we can see that string concatenation operation is slower than the string    interpolation operation.

  • In ruby destructive operations are faster, we all know destructive operations are risk prone, as they modify the actual value, instead of modifying the copy. But if we have such use-cases where, we want to modify the actual object, than we should go for this destructive ones
  hash1 = {"color": "blue", height: 100}
  hash2 = {"width": 200}
  Benchmark.bm do |x|
    x.report {hash1.merge(hash2)}
    x.report {hash1.merge!(hash2)}
  end

  [#<Benchmark::Tms:0x000000000b090078 @cstime=0.0, @real=7.367998478002846e-06, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>,
   #<Benchmark::Tms:0x000000000b08f880 @cstime=0.0, @real=3.569999535102397e-06, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>]

As we can see from the above benchmarking, destructive operations are nearly two times faster than the normal operations.

  • Parallel Assignments are slower than the normal assignment
  Benchmark.bm do |x|
    x.report {var1,var2 = 1, 2}   #parallel assignment
    x.report {var1 = 1; var2 = 2} 
  end

  [#<Benchmark::Tms:0x000000000a2d59d8 @cstime=0.0, @real=8.679999154992402e-06, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>,
   #<Benchmark::Tms:0x000000000a2d5230 @cstime=0.0, @real=5.723002686863765e-06, @cutime=0.0, @label="", @stime=0.0, @total=0.0, @utime=0.0>]

Just look at the above benchmark output, it justifies that parallel assignments are slower.

  • Magic statement in Ruby:  frozen_string_literal

In ruby, we know that strings are mutable, what does that even mean?

In order to understand this, Let’s take an example:

  hash1 = {"width": 200}
  
  def get_width
    hash1["width"]
  end

In the above code, whenever get_width will be accessed, it will always allocate memory for the string “width”. so, in order to solve this, ruby introduced the concept of “freeze”, now calling the above code like this will solve the problem.

 
  def get_width
    hash2["width".freeze]
  end

But using freeze, everywhere with strings, will makes our code unclean and not DRY.
So, for this Ruby 2.3 introduced MAGIC COMMENT, termed as frozen_string_literal.

When we add this magic comment “frozen_string_literal” to any ruby file, all the strings within that file will be treated as immutable resulting in improving our code performance.

  # frozen_string_literal: true

  hash1 = {"width": 200}
  
  def get_width
    hash1["width"]
  end

For more information like this, stay tuned 🙂