ruby on rails interview questions
It’s a mixed collection from other source and mine(I will be keep updating the blog)
1. meta-programming
Metaprogramming is writing code that writes code during runtime. As a dynamic language, Ruby gives you the freedom to define methods and even classes during runtime. Metaprogramming with Ruby, one can do in a few minutes what other languages may take hours to do
2. proc and lamda from
https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas
A lambda is a way to define a block & its parameters with some special syntax. You can save this lambda into a variable for later use
my_block = -> { puts "sample lambda code" }
my_block.callmultiple_block = ->(x) { x * 2 }
multiple_block.call(10)
# 20
Proc
Procs are a very similar concept. One of the differences is how you create them. Another difference between procs
& lambdas
is how they react to a return
statement.
def call_proc
puts “Before proc”
my_proc = Proc.new { return 2 }
my_proc.call
puts “After proc”
end> p call_procoutput :
Before proc
2def call_lambda
puts "Before lambda"
my_lambda = -> { return 1 }
my_lambda.call
puts "After lambda"
end> p call_lambda
Before proc
After proc
nil
A lambda
will return
normally, like a regular method. But a proc
will try to return
from the current context.
Here is a summary of how procs
and lambdas
are different:
- Lambdas are defined with
-> {}
and procs withProc.new {}
. - Procs return from the current method, while lambdas return from the lambda itself.
- Procs don’t care about the correct number of arguments, while lambdas will raise an exception.
Taking a look at this list, we can see that lambdas
are a lot closer to a regular method than procs
are.
3. ruby is dynamic typed language / duck typing
Statically typed languages, This means that when you associate a variable to a type then you cannot change it anymore.
In C
int main(){
int x;
x = "rubycademy.com"; // warning: incompatible pointer to integer conversion assigning to 'int' from 'char [15]' [-Wint-conversion]
return (0);}
Note that statically typed languages are generally compiled language, as the compiler can type-check each variable through multiple defined constraints at compile time.
Dynamically typed languages, This means that when you associate a variable to a type then you can change it whenever you want.
Actually, typing is associated with the value it assumes rather than the variable itself.
a = 'test'
a.class #Stringa = true
a.class #TrueClass
So the type is defined at runtime
4. N+1 queries
pry(main)> ur = UserRole.last(2)UserRole Load (1.0ms) SELECT "user_roles".* FROM "user_roles" ORDER BY "user_roles"."id" DESC LIMIT 2=> [#<UserRole id: 736, user_id: 478, role_id: 4, created_at: "2019-03-20 08:03:42", updated_at: "2019-03-20 08:03:42">,#<UserRole id: 737, user_id: 478, role_id: 5, created_at: "2019-03-20 08:03:42", updated_at: "2019-03-20 08:03:42">]pry(main)> ur.first.userUser Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 478]]=> #<User id: 478, first_name: "ganga", last_name: "df", email: "praaveen.vr+ganga@spritle.com", tenant_id: 190, created_at: "2019-03-20 08:03:41", updated_at: "2019-03-20 08:05:48", encrypted...
The above code works, but it makes far too many independent database queries. For example in order get the user of last two user role, above code will have 3 queries.
Eager Loading in Rails
pry(main)> ur = UserRole.includes(:user).last(2)
UserRole Load (0.6ms) SELECT "user_roles".* FROM "user_roles" ORDER BY "user_roles"."id" DESC LIMIT 2
User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (478)=> [#<UserRole id: 736, user_id: 478, role_id: 4, created_at: "2019-03-20 08:03:42", updated_at: "2019-03-20 08:03:42">,
#<UserRole id: 737, user_id: 478, role_id: 5, created_at: "2019-03-20 08:03:42", updated_at: "2019-03-20 08:03:42">]pry(main)> ur.first.user=> #<User id: 478, first_name: "ganga", last_name: "df", email: "praaveen.vr+ganga@spritle.com", tenant_id: 190, created_at: "2019-03-20 08:03:41", updated_at: "2019-03-20 08:05:48" ....>
but with includes(:user) only 2 queries.
Event if you request for 100 records with include it will be only 2 query but with out include will make 100 +1 queries
5. delegate
delegate
provides a delegate class method to easily expose contained objects’ public methods as your own. Simply say, through delegation you can use public methods in other model directly.
6.Difference between include and extend
Instead of including
the module, you can (less commonly) also extend
it. The difference is that including
the module makes all the module's methods instance methods whereas extending
the module makes all its methods class methods (e.g. as if it prepended each one of them with self.
).
include is used bringing all the methods of a module into the class as instance
methods. These are mixins
used in Ruby as it does not support Multiple inheritance.
An Example
You can see both of these in action below:
module ModuleExample
def foo
'foo'
end
end# Including modules binds the methods to the object instance
class Person
include ModuleExample
end# Extending modules binds the methods to the class itself
class Book
extend ModuleExample
end# IRB
> Person.foo
# => NoMethodError: undefined method `foo' for Person:Class
> Person.new.foo
# => 'foo'
> Book.foo
# => 'foo'
> Book.new.foo
# => NoMethodError: undefined method `foo'
7. Difference between Load and require
First of all, include
and extend
are language-level methods where as require
and load
are file-level methods. But all methods are used to support DRY concept of Ruby.
8. callbacks
Filters: Filters are methods that are run before, after or “around” a controller action
Callbacks: Callbacks allow you to trigger logic before or after an alteration of an object’s state in model.
9. Explain what is ORM in rails ?
ORM stands for Object-Relational-Mapping. It basically means that Active Record takes data which is stored in a database table using rows and columns, which needs to be modified or retrieved by writing SQL statements (if you’re using a SQL database), and it lets you interact with that data as though it was a normal Ruby object.
Example: Suppose you want to fetch an array of all the users then instead of writing any code for database connection and then writing some SQL query like
SELECT * FROM users
and converting the result into an array, I can just typeUser.all
and Active Record gives me that array filled with User objects that I can play with as I'd like.
It doesn’t really matter which type of database you’re using. Active Record smooths out all the differences between those databases for you so you don’t have to think about it. You focus on writing code for your application, and Active Record will think about the nitty gritty details of connecting you to your database. It also means that if you switch from one database to another, you don’t actually need to change any major application code, just some configuration files.
10. databases indexes
If you are looking to increase the performance of your data driven web application, the answer may be as simple as adding an index to the correct column of your database table.
A database index is exactly what it sounds like. If you think of the index at the back of a reference book: a quickly searchable list of pointers to get to the actual data. Without an index, a database query might have to look at every row in your database table to find the correct result.
For more details refer the link.
11. About stackoverflow contribution?
online community for anyone that codes to learn, share their knowledge, and build their careers.
12. About version controller(eg: git) ?
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
13. github repos and contributions?
14.Active Record Associations
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
a. Choosing Between has_many :through and has_and_belongs_to_many
You should use
has_many :through
if you need validations, callbacks or extra attributes on the join model.
b. Choosing Between belongs_to and has_one
c. Polymorphic Associations
https://launchschool.com/blog/understanding-polymorphic-associations-in-rails
A slightly more advanced twist on associations is the polymorphic association. With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model. Here’s how this could be declared:
class Picture < ApplicationRecordbelongs_to :imageable, polymorphic: trueendclass Employee < ApplicationRecordhas_many :pictures, as: :imageableendclass Product < ApplicationRecordhas_many :pictures, as: :imageableend
d.Self Joins
https://medium.com/@TheDickWard/self-referential-relationships-aka-self-joins-in-rails-64f8f36ac311
In designing a data model, you will sometimes find a model that should have a relation to itself. For example, you may want to store all employees in a single database model, but be able to trace relationships such as between manager and subordinates. This situation can be modeled with self-joining associations:
class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee",
foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
With this setup, you can retrieve @employee.subordinates
and @employee.manager
.
c. Single Table Inheritance
https://devblast.com/b/single-table-inheritance-with-rails-4-part-1
Sometimes, you may want to share fields and behavior between different models. Let’s say we have Car, Motorcycle and Bicycle models. We will want to share the color
and price
fields and some methods for all of them, but having some specific behavior for each, and separated controllers too
Compare STI and Polymorphic
15. Explain Cross-Site Request Forgery (CSRF) and how Rails is protected against it?
CSRF is a form of attack where hacker submits a page request on your behalf to a different website, causing damage or revealing your sensitive data. To protect from CSRF attacks, you have to add “protect_from_forgery” to your ApplicationController. This will cause Rails to require a CSRF token to process the request. CSRF token is given as a hidden field in every form created using Rails form builders.
16.Design patterns
Reference
https://www.sitepoint.com/7-design-patterns-to-refactor-mvc-components-in-rails/
https://naturaily.com/blog/ruby-on-rails-design-patterns
a. Service design pattern
b. Decorator design pattern
17. oauth2
18.Multi tenancy
https://medium.com/@praaveen/multi-tenancy-and-sub-domain-lvh-with-rails-f5167b550be6
a. act_as_tenant gem
b. appartment gem
Difference between these two gems
19.Monkey patching
Reference : https://culttt.com/2015/06/17/what-is-monkey-patching-in-ruby/
One of the most powerful aspects of Ruby is the ability to re-open any class and change it’s methods.
Yes that’s right, you can actually reopen any class and change how it works. This includes the standard Ruby classes like String
, Array
or Hash
!
Now this is obviously as dangerous as it sounds. Being able to change the expected outcome of a method can cause all sorts of weird behaviour and difficult to track down bugs.
But nonetheless, the ability to “Monkey Patch” any class is extremely powerful. Ruby is like a sharp knife, it can be extremely effective, but it’s usually your own fault if you cut yourself.
20. Difference between each, map, collect
21. Dependency delete
22. index: true vs foreign_key: true (Rails)
23. About rake and rack
24. micro services
25. Application server
26. Web server in rails
27. About HTTP and HTTPS
28. Client Server communication(request and response)
29. Cookies, session
30. soft delete
31. websocket
32. rspec
33. Meta programming examples
34.Code refactor
35.ruby snippets for skill testing
36.Difference between find and find_by_id
37.Keep up to date in ruby and rails versions
39. Any gem you have worked
40. Devise gem
41. database Queries
42. counter_cache
Instead of counting the associated records in the database every time the page loads, ActiveRecord’s counter caching feature allows storing the counter and updating it every time an associated object is created or removed.