Accreditation Bodies
Accreditation Bodies
Accreditation Bodies
Supercharge your career with our Multi-Cloud Engineer Bootcamp
KNOW MORERuby on Rails is a full-stack framework offering sufficient tools needed to build amazing web apps on both the front and back end. It has gained momentum and left behind all other framework alternatives. Thus, is very popular among developers. Here is a list of the top, expert-curated list of Ruby on Rails interview questions and answers that will help you ace interviews related to Ruby on Rails. It is a dynamic, flexible, and robust framework that has been preferred by several organizations of all sizes and is in great demand. To get a detailed understanding of Ruby on Rail's technical interview questions, you must go for Ruby on Rails training. If you just getting started with RoR, then this guide will help you achieve your goals with detailed information covering questions and answers from freshers to advanced levels with simple coding examples to help you get through concepts.
Filter By
Clear all
Rails is a web application development framework based on the Ruby programming language. It is designed to help developers by making the development work more accessible and streamlined. Rails is a high-level, interpreted programming language compatible with different programming paradigms. Rails, however, is a framework that can be used to build innovative, robust, and secured web applications.
Expect to come across this popular question in the Ruby on Rails interview.
Below are the significant benefits of using RoR for web development.
Below are some disadvantages that need to be considered while working with RoR.
Below are the use cases where RoR is the perfect fit.
Examples of famous applications built on Ruby are-
A staple in Ruby and Rails interview questions, be prepared to answer this one. ORM is the short form for the Object Relational Model that helps connect an application's objects to tables within a relational database management system. It lets you store and access the properties and relationships of the application’s objects from a database without running the SQL statements directly.
ORM is a library that encapsulates the code for manipulating the data without needing (SQL) anymore but uses an object of your language.
False and nil are the built-in data types in Ruby. Both are different and has different meaning.
Nil | FALSE |
---|---|
nil is a NilClass object | false is a FalseClass object, |
not a valid value | is a valid value |
does have a type | is a boolean data type |
Both are different and have a different purposes in ruby on rails. Considering syntactically, strings are the text that is enclosed within the quotation marks, while the symbol is the text that starts with a colon sign.
Ruby symbols are “scalar value objects that you can use as identifiers, mapping immutable strings to fixed internal values.” Symbols are immutable strings that you cannot change.
Symbols are approx 1.7 times faster than Strings. If you use the same symbol multiple times, they will have the same object ID, referring to the same object. While, Strings will be a different object with a unique object ID, referring to different objects.
Rails controller is the logical part of the application. It orchestrates the user's interaction with the views and the model. There are other significant roles of the controller-
C:\ruby\library> ruby script/generate controller Subject.
Notice that we have capitalized the Subject and used the singular form. This command accomplishes several relevant tasks:
It will create the file called app/controllers/subject_controller.rb, witht he following content
class SubjectController < ApplicationController
end
The Controller classes inherit from ApplicationController, which is available in the other file in the controller's folder, called application.rb.
A rails migration is a tool that allows you to alter the application’s database schema. Instead of using SQL scripts, you can use domain-specific language to define the database's modifications. As the code in RoR is database-agnostic, you can easily port the project to another platform. You can roll back and manage the modifications alongside your application source code.
We can use the following command to create a migration.
For this, we can use the rails generates command in the rails command prompt.
Go to start>>Railsinstaller>>command prompt, then root your application directory.
Use the following code.
Rails generate migration record1.
The migration file will convert to camel Case to underscore: record_1.rb with the current date and time, as shown.
The file will be stored in the db directory inside migrate, and that file has a Ruby class defined in it.
This is a frequently asked question in Ruby on Rails basic interview questions. Whenever we create an object, memory is allocated to it. Ruby supports two different types of memory. The first is the malloc heap, where the entire program is included. This memory will be released back to the operating system if the memory is known to be unused by Ruby at the end of a garbage collection.
The second is the Ruby object heap, a subset of the malloc heap that holds the most Ruby objects. If objects are large, they point to the malloc heap. The Ruby heap is consistently monitored and cleaned by the Ruby garbage collector.
Ruby works on the mark and sweep garbage collection algorithm that uses three colors. That marks every object with either white, black, or gray, hence the name tricolor
Each variable in Ruby is declared by placing a special character at the start of the variable name. Variables store some values that can be accessed and used within the program based on their scope.
Below are different types of variables available in Ruby.
Local variables- these are the local variables we can use within the code block where they are declared. We use symbol [a-z] or _
For example-
pi = 3.1415 def valueofpi pi = 3.142 puts "Value of pi inside valueofpi = #{pi}" end valueofpi() puts "Value of pi = #{pi}"
Instance variables- these variables are like Class variables whose values are local to specific instances of an object. We can use the instance variables across methods for any specified instance or object i.e., and instance variables can change from object to object. We use the symbol @.
For example-
class Employee def set_data(empName, empAge) @name = empName @age = empAge end def get_name() return @name end def get_age() return @age end end e1 = Employee.new e1.set_data("rita", 24) e2 = Employee.new e2.set_data("sita", 31) puts "Employee #1, Name = #{e1.get_name()}, Age = #{e1.get_age()}" puts "Employee #2, Name = #{e2.get_name()}, Age = #{e2.get_age()}"
Class variables- these variables starts with @@ sign that are available across different objects. A class variable belongs to the class, and it is a characteristic of a class. They are also known as the global variables within the context of a single class.
For example-
@@no_of_customers = 0
Global variables- always starts with $. Its scope is global, which means we can access it from anywhere in a program.
For example-
$message = "hello" def changeMessage $message = "heh" puts "msg change #{$message}" end puts "changed msg #{$message}" changeMessage()
Load reads and parses files every time during file execution. However, in most cases, developers use the “require” method. But there are some scenarios where we want to use the “load” to pick the latest module changes within the class
Below is the syntax-
load 'filename'
Require is used to read the file from the file system, parse it, save it to the memory, and run it in each place. If you make any changes to the file while the script is running, the “require” will not pick the changes as Ruby will use the file from th memory.
Below is the syntax-
require 'filename'
MVC is the framework that divides any extensive application into three parts.
Working of MVC-
Access modifiers are an important concept of the object-oriented programming language that restricts the visibility of methods and member fields to protect against accidental changes to the code. Regarding access control, Ruby is different from other Object Oriented Programming languages.
We have 3 different access modifiers in Ruby, namely -
Ruby offers a program called ERB, which stands for Embedded Ruby. It is used when you need to directly put the codes associated with Ruby into the HTML files, irrespective of the size and complexity of the codes.
Editors are used to writing code. Ruby supports the usage of various editors. We can choose any editor as per our requirements and with ease.
The active records represent the “M” of the MVC, which is the system layer responsible for representing the business data and logic. It lets you access, create, read, update, and delete the data from the relational database. It is a core part of the MVC design.
Basic functionalities of the active record are-
Gems are used to extend the functionalities of their distributions. Some gems get automatically installed with Ruby installation, while you need to install some explicitly. Also, you can have different versions of the same gems installed in your system.
Execute the following command to get the list of all the gems available.
rvm gemset list
RVM is a command-line tool that allows us to easily install, manage, and work with different ruby environments, from interpreters to sets of gems. The GitHub community maintains RVM through pull requests sent to the project repository. It lets us deploy each project with its own self-contained and dedicated environment.
Below is the basic RVM syntax-
rvm command_options command ruby_to_act_on.
For upgrading the RVM, we use the following command.
rvm get head
Rails bundler offers a constant environment for applications by tracking required gems.
You can use the following command to use the specific bundler.
Gem install bundler. The gem bundler bundles all the suitable gems required by any specific application to work efficiently. Bundling Rails and other dependencies might increase the size by a few megabytes.
Fixtures allow you to organize data that you want to test against and can feed into your unit testing. The fixtures will be created automatically when rails generate any test for the controllers and models. They are just for test purposes, and you cannot access them while running the application.
Typically fixtures are expressed in terms of YAML files.
For example-
# orders.yml payments_equal_line_item_total: # no attributes needed # line_items.yml electric_polisher: order: payments_equal_line_item_total name: 'Electric polisher' price_cents: 400
Each YAML fixture is given a name and is followed by an indented list of key/value pairs in the “key: value” format. A blank line separates records for your viewing pleasure.
The differences below will help you understand where to use strings and symbols.
If the text available is “data,” then use a string. But, if it is code, then use a symbol.
Symbols are not text; they are unique identifiers and are static, such as numbers, bar codes, etc., while, unlike symbols, strings be easily changed.
You can use strings containing the exact text within the code multiple times by creating a new string object. While, for using the symbol, the number of times you do put, it will only create one object and can be reused.
For example-
# Symbols (same id) :foo_bar.object_id # => 2386588 :foo_bar.object_id # => 2386588 # Strings (different ids) "foo_bar".object_id # => 1020 "foo_bar".object_id # => 1040
You can use destroy to delete the record from the rails along with all dependencies. For example, the authors or other details associated with the book will all be deleted if you want to delete a book record.
For example-
$ rails console Loading development environment (Rails 3.2.9) >> book = Book.create(title: 'example) (0.1ms) begin transaction SQL (25.8ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Sun, 18 Nov 2012 15:11:41 UTC +00:00], ["title", "example"], ["updated_at", Sun, 18 Nov 2012 15:11:41 UTC +00:00]] (2.1ms) commit transaction => # >> Book.count (0.3ms) SELECT COUNT(*) FROM "books" => 1 >> book.destroy (0.1ms) begin transaction Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = 1 SQL (0.3ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 1]] (3.0ms) commit transaction => # >> Book.count (0.2ms) SELECT COUNT(*) FROM "books" => 0 >>
Objects are the core building blocks of any OOP program. The same goes with Ruby on rails. An object is a combination of data and methods used to communicate through methods. Each object can receive messages, send messages, and process data.
For creating an object. We must define a class, a template for an object describing the state and behavior that the class objects all share. We can create many objects for a class. Objects created at runtime from a class are called instances of that class.
For example-
#!/usr/bin/ruby class Being end b = Being.new //object creation puts b
In ruby, “==” returns true if the two comparison entities are the same. For example, if a=1.
At the same time, “equal” will check if both entities are the same object. For example- a.equal?(b) iff a is the same object as b
These are nonexecutable parts of a program. We can write comments in between our programs for reference purposes. We can write on one line or span multiple lines of comments.
One-liner comment
# one-liner
Multiple line comments
=begin Hello This Is
Multi line comment
=end
Rake is a commonly used task management and build automation tool, allowing users to specify tasks and their related dependencies and group tasks in a namespace. You can also say that rake is the task runner that manages tasks like creating database backup, running tests, and gathering necessary reports. Without a rake, all the tasks will be scattered for all projects. It helps in accessing the tasks centrally.
When we must run the rake task, we must ensure the following.
RubyMine allows running an arbitrary Rake task. For example, we will see how we can run the db:migrate task for migrating a database in the Rails application.
Run a task using Run Anything.
Press ^ twice and type db:migrate in the invoked popup. Select rake db:migrate from the list and press enter.
Go to the main menu, select Tools | Run Rake Task ⌥ R. type g db:migrate in the popup, select db:migrate, and press enter.
Select the required migration version and the environment from the popup. Click OK.
Run a rake text from the editor
Open *.rake file. Click the Run Rake Task button on the gutter next to the required task or Place the caret at the required task name and press. ⌥ ⏎
Take the required action whether to run or debug the task, select Run '<task name>' or Debug '<task name>'. Press enter.
After the task is executed, RubyMine automatically creates a unique profile - a temporary run/debug configuration where we can customize the settings of this configuration.
It's no surprise that this one pops up often in interview questions about Ruby on Rails. You can use the destructive method to alter the state of an object. String, Array, Hash, and others have such methods. The method has two different versions, one with a plain name, the other with the same name, followed by !. The plain version will create a copy of the receiver, make the required change, and return the copy. The other or the “bang” version (with the !) alters the receiver in place.
Rails filters are methods that run either before or after the execution of the controller's action method. You can use this filter method when you want to ensure that a given code block runs with a specified action method called.
There are three filter methods:
Before filters- Rails before filters are executed before the code in the action controller. They are defined at the top of a controller class that calls them. To set it up, you need to call the before_filter method.
For example-
class UserController < ApplicationController before_filter :verify_password def verify_password ... end end
After filters- these filters are executed after the code in action controller executes. Just like before filters, after filters are also defined at the top of a controller class that calls them. We need to use the after_filter method to set it up.
For example-
class PhotoController < ApplicationController after_filter :resize_photo def resize_photo ... end end
Around filters- Rails around filters contain codes that can execute both before and after the execution of the controller's code. They are used when you need both before and after the filter. Implementing around filters is more complex than the other two filters. It is defined by a common class containing both before and after methods.
For example-
class ActionLogger def before(controller) @start_time = Time.new end def after(controller) @end_time = Time.now @elapsed_time = @end_time.to_f - @start_time.to_f @action = controller.action_name table end end
Observers are the simple method, allowing one object to inform a set of objects when its State changes. It is used when a one-to-many relationship exists between the object. If one object gets a notification, another dependent object will also get a notification and update automatically.
Execute the following command to create an observer.
$ rails g observer User
We will explain this with a simple example where we would like to send emails to the user based on their activity status.
class User < Activerecord::Base after_save :send_email private def send_email if status_changed? UserNotificationMailer.account_open_email(self).deliver if status=='created' UserNotificationMailer.account_activated_email(self).deliver if status == 'active' UserNotificationMailer.account_deactivation_email(self).deliver if status =='deactive' end end End
The above code works fine as expected. But there is some issue. Yes, our model job is not to send emails. It will violate the Single Responsibility Principle. So better to implement the observer pattern here.
We will now create a UserObserver class inside the model, which will inherit from ActiveRecord::Observer.
class UserObserver < ActiveRecord::Observer def after_save(record) if record.status_changed? UserNotificationMailer.account_open_email(record).deliver if record.status=='created' UserNotificationMailer.account_activated_email(record).deliver if record.status == 'active' UserNotificationMailer.account_deactivation_email(record).deliver if record.status =='deactive' end end end
Callbacks are commonly used within an object’s life cycle at certain moments, such as after a state change. While using callbacks, you can write codes while creating, saving, updating, deleting, loading, or validating the active record object from the database.
It will give you greater control of data and the applications using it. It changes the usual flow of the code, resulting in complicated debugging and test-making.
There are three types of callbacks.
For using a callback, we need to “register” it at the top of your Model using method specifying the type, such as before_create. We can either pass that method a symbol that corresponds to the method name or write the callback as a block at once.
For example
class User < ActiveRecord::Base before_create do |user| puts "Creating #{user.name}" end after_create :Created private def just_created puts "User Created." end End
In this example, we create a class linked with the database. We call the before_create to check some requirements. Then, call the after_create, which displays the message.
The harness lets you view high-level application metrics collected from various sources and forward them to the collector. You can use any collector that can simply implement the Statsd interface. The harness takes the metrics from ActiveSupport::Notifications and forwards them to the collector.
The harness automatically assumes that the collector can do proper metric aggregation and statistics. For example, using the statsd will calculate the 70th percentile and averages.
You can use a harness specially for very high-traffic applications. Each metric is processed in a separate thread, where the main thread will do just sufficient work.
A symbol is mostly confused with variables, but both are different. Symbols are written like this: “:something,” preceded by a colon. Typical symbols do not contain spaces. So, if you want to create a symbol with multiple words, you need to use underscores, like so: :another_funny_symbol.
//add use cases//
A Proc object encapsulates the code block you can store within a local variable, pass to a method or another Proc, and be called.
For example
square = Proc.new {|x| x**2 } square.call(3) #=> 9 # shorthands: square.(3) #=> 9 square[3] #=> 9
def gen_times(factor) Proc.new {|n| n*factor } # remembers the value of factor now of creation end times3 = gen_times(3) times5 = gen_times(5) times3.call(12) #=> 36 times5.call(5) #=> 25 times3.call(times5.call(4)) #=> 60
count() is an Array class method that returns the total number of elements present within the array. Count uses three different approaches.
Count all: do not require any parameter and will return a count of all the rows.
For example
Person.count # returns the total count of all people
Count using column: pass a column name to count and will return a count of all the rows for that column present.
For example-
Person.count(:age) # returns the total count of all people whose age is present in the database
Count using options will find the row count based on the options.
For example-
Person.count(:conditions => "age > 26") Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN. Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id") # finds the number of rows matching the conditions and joins. Person.count('id', :conditions => "age > 26") # Performs a COUNT(id) Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*')
The size() is a method that is inbuilt into ruby. It returns the size of the set. Simply put, it will return the number of elements present in the set.
For example-
require "set" s1 = Set[11,2,3,4,5] # size method used puts s1.size()
This question is a frequently asked question in Ruby on Rails interview questions. Ruby offers a mechanism for handling exceptions effectively. We need to enclose the code raising or throwing an exception in a begin/end block and use rescue clauses to tell Ruby the types of exceptions we want to handle.
Below is the syntax for exception handling in Ruby
Syntax
begin # - rescue OneTypeOfException # - rescue AnotherTypeOfException # - else # Other exceptions ensure # Always will be executed End
The code within the begin/rescue block is protected. If any error occurs while executing this block, the control will pass to the block between the rescue and end.
For each rescue block, ruby will compare the raised exception for the match and parameters. If the exception name and the name in the rescue parameter are the same, then the block will execute, and the output will be displayed.
For example-
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "file is open" end rescue file = STDIN end print file, "==", STDIN, "\n"
You will get below output-
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Initializers are class instance members that get called whenever a class’s object is created. We must use the name initialize for Initializer.
For example, for an Employee class, we must have an instance method by the name initialize.
Ruby supports two types of initializers.
Parameterless initializer Parameterized initializer For example- parameterless initializer class Employee def initialize @employeeId = 1 @employeeName = "sita" end def setEmployeeId(empId) @employeeId = empId end def setEmployeeName(empName) @employeeName = empName end def getEmployeeId return @employeeId end def getEmployeeName return @employeeName end end
We can use this initializer when we want to set some default values for employee objects. Now create employee object as shown below.
employee1 = Employee.new puts "Employee ID is #{employee1.getEmployeeId()}" puts "Employee Name is #{employee1.getEmployeeName()}"
For example- parameterized initializer
class Employee def initialize(empId, empName) @employeeId = empId @employeeName = empName end def setEmployeeId(empId) @employeeId = empId end def setEmployeeName(empName) @employeeName = empName end def getEmployeeId return @employeeId end def getEmployeeName return @employeeName end end
We can use this initializer when we want to set values for employee attributes while creating the object. Here, we have a parameterized constructor for the Employee class accepting ID and name and assigning it to the Employee object.
Now, create an employee object with parameters as shown below.
employee1 = Employee.new(23, "abc") puts "Employee ID is #{employee1.getEmployeeId()}" puts "Employee Name is #{employee1.getEmployeeName()}"
Functions are a combination of procedural statements that uses functions to execute specific code. For example, a function to perform addition need to declare two variables and add them. A function can return a value to the method that calls that function. If a function does not return a value to the caller, the value is None.
For example-
def add() a = 10 b = 20 return a + b end print add()
Scaffolding refers to the auto-generation of a simple set of a model, views, and controllers, usually for a single table.
Two types of scaffolding are available in Ruby- static and dynamic.
Below is the basic difference between static and dynamic scaffolding.
Dynamic Scaffolding | Static Scaffolding |
---|---|
It generates all content and user interface at runtime. | We need to provide an explicit entry in the command to generate the data with their fields. |
We can create new, delete, and modify methods for usage in your application. | Such a generation does not need to occur. |
Synchronization is not necessary with a database. | It necessitates the migration of the database. |
These are PostgreSQL, DB2, MySQL, SQL, and SQLite.
No doubt, Ruby applications are highly scalable. The significant reasons are: horizontal scaling and is thread-safe. In other words, it will help your application handle more traffic by providing support for additional Ruby processes and adding additional servers.
The Rails console is a command line utility running the Rails applications from the command line, an extension of Ruby IRB. It offers all the facilities of IRB and the ability to auto-load the Rails application environment, including all its classes and components.
A must-know for anyone heading into a Ruby on Rails interview, this question is frequently asked in Ruby Interview Questions. Active Job is a framework to declare and run the jobs on different queueing backends. You can use any job, from regularly scheduled clean-ups to billing charges to sending emails. It is suitable for those tasks that you can split into several small tasks that can be executed simultaneously.
The strong parameters provide an interface that protects the attributes from the end-user assignment. In this case, the Active model does not use the Action Controller parameters for mass assignment until they are explicitly enumerated.
Also, you can mark the parameters as required and flow through a predefined flow to end up as a 400 Bad Request without effort.
Different naming conventions exist for variables, constants, methods, parameters, classes, models, controllers, and modules.
Local variables
example = 0
example_variable = 0
Instance variables
@example
Class variables
@@example
Global variables
$example
CONSTANTS
EXAMPLE_CONSTANT
Methods
def example
End
Parameters
def some_method (example)
end
Classes
ClassExample
Models
Example
Controllers
ExamplesControler
Modules
ModuleExample
Inheritance allows a class to inherit the attributes and behavior of another class. The class that inherits is called the subclass or the child class, and the inherited class is called the superclass or parent class.
Inheritance uses the syntax Subclass < Superclass. If you have C < A, then class C is a child class of A, C inherits from A, or A is the parent of C.
For example,
class Exam def initialize puts "Superclass" end def super_method puts "Method of superclass" end end class Sudo_Placement < Exam def initialize puts "Subclass" end end Exam.new sub_obj = Sudo_Placement.new sub_obj.super_method
Finders in rails help you find specific records with or without any mentioned conditions.
For example-
To find an author with id 50
Author.find(50)
To find authors with id- 20, 30, 40.
author.find([20, 30, 40])
To find the author with the first name as “sita.”
Author.find :all :condition => ["first_name =?", "sita" ]
Available options to be used for finders- :order, :offset, :limit, :group, :joins, :include, :select,: readonly.
If you want to make your application ready for multiple databases, then you need to do that explicitly. Suppose we have an application with a single writer database, and we want to add a new one. Then you must make changes to the database.yml file.
Existing database.yml production: database: my_prim_database adapter: mysql2 username: root password: <%= ENV['ROOT_PASSWORD'] %>
First, add a replica for the existing configuration, and a second database called pet and a replica for that.
New database.yml
production: primary: database: my_prim_database username: root password: <%= ENV['ROOT_PASSWORD'] %> adapter: mysql2 primary_replica: database: my_prim_database username: root_readonly password: <%= ENV['ROOT_READONLY_PASSWORD'] %> adapter: mysql2 replica: true animals: database: my_pet_database username: pet_root password: <%= ENV['PET_ROOT_PASSWORD'] %> adapter: mysql2 migrations_paths: db/pet_migrate animals_replica: database: my_pet_database username: pet_readonly password: <%= ENV['PET_READONLY_PASSWORD'] %> adapter: mysql2 replica: true
Note
Rails::Engine lets you wrap a specific Rails application or a subset of functionality to share it with other applications or within a more extensive packaged application. Every Rails::Application is just an engine allowing simple features and application sharing.
//Add code examples//
It offers you a framework that compresses JavaScript and CSS assets. You can use it to write these assets in other languages and pre-processors such as CoffeeScript, Sass, and ERB. Using this, you can automatically combine your assets with assets from other gems.
You can implement the asset pipeline using the sprockets-rails gem enabled by default. To disable it while creating a new application, you must pass the --skip-asset-pipeline option.
One of the most frequently posed Ruby interview questions, be ready for it. The closure is a function or a code block with variables bound to the environment from which the closure is called. The closure is used as a variable that you can assign to another variable or pass to any function as an argument.
You can define a closure block in one scope and call it in a different scope.
Closure can recognize the variable available within its scope at the creation time and, while calling it, can access the variable even if they are not in the current scope.
Examples of closure in ruby are- Blocks, procs, and lambda.
Blocks are the simplest form of closure, a code piece enclosed between braces {} or do…end.
You can pass more than one variable to the block.
You can use a yield statement to call a block within a method with a value.
It does not have a specific name.
Below is the syntax for creating a block.
block_name { #statements_to_be_executed } Using do…end block_name do #statement-1 #statement-2 . End
For example-
arr = [10, 11, 13, 41, 59] arr.each do | item | puts item End
The forEach() method allows you to loop through each element of an array/object. The forEach() method takes a callback function as an argument invoked for each array element. It is like the for loop but without a return value.
The map() method loops through each element of an array/object. The map() method takes a callback function as an argument that is invoked for each array element. It is like the forEach() method but returns a new array.
Below is the syntax for the map.
array = ["a", "b", "c"]
array.map { |string| string.upcase }
# ["A", "B", "C"]
First, we will have an array. It could be a hash or range. Then we will call a map with a block. It will return a new array with the results. The result will not change, but you can use the map to change the original array.
For example-
Doubling the numbers of an array.
array = [1,2,3]
array.map { |n| n * 2 }
# [2, 4, 6]
Converting string to numbers.
array = ["11", "21", "5"]
array.map { |str| str.to_i }
# [11, 21, 5]
Indexing values with the “with_index” method.
array = %w(a b c)
array.map.with_index { |ch, idx| [ch, idx] }
# [["a", 0], ["b", 1], ["c", 2]]
Lambdas are procs that have distinguishing factors. They are considered the “regular” methods in two ways: they enforce the number of arguments that need to be passed when called, and they use "normal" returns.
When calling a lambda that expects an argument without one, or if you pass an argument to a lambda that does not expect it, an ArgumentError. Will be raised.
irb> lambda (a) { a }.call ArgumentError: wrong number of arguments (given 0, expected 1) from (irb):8:in `block in irb_binding' from (irb):8 from /Users/jeff/.asdf/installs/ruby/2.3.0/bin/irb:11:in `<main>'
Also, for a lambda, the return keyword is same as it is for a method. When calling a proc, the program yields control of the code block. So, if the proc returns, the current scope returns. If a proc is called inside a function and calls return, the function immediately returns.
def return_from_proc a = Proc.new { return 10 }.call puts "not printed." end
The above function will yield control to the proc, so when it returns, the function returns. Calling the function in this example will never print the output and return 10. So we use lambda.
def return_from_lambda a = lambda { return 20 }.call puts "The lambda returned #{a}, and this will be printed." End
When using a lambda, it will be printed. Calling return in the lambda is like calling return in a method, so the “a” variable is populated with “20,” and the line is printed to the console.
With hashes, we can store data as key-value pairs. You can retrieve and modify data using the key.
For example-
countryCapitals = {} countryCapitals["India"] = "Delhi" countryCapitals["United States"] = "D.C." countryCapitals["United Kingdom"] = "London" puts "Count is = #{countryCapitals.length}" # Using Subscript to query the dictionary for a key and get the value. puts "Capital of India is = #{countryCapitals['India']}" # iterate the hash using each countryCapitals.each do |key, value| puts "#{key} => #{value}" end # if the hash contains NYC as a key. puts "ContainsKey - NYC?: #{countryCapitals.key?("NYC")}" # if the dictionary contains London as a value. puts "ContainsValue - D.C.?: #{countryCapitals.has_value?("London")}" # remove an entry from the dictionary. countryCapitals.delete("India") # Print the hash
puts countryCapitals
Computer systems are connected via networks. Two commonly used protocols in a network.
TCP - Transmission Control Protocol.
UDP - User Datagram Protocol.
Network protocol implementations for TCP come under the TCPSocket class. TCP protocol provides same-order communication, which is useful for other protocols like HTTP, SecureFTP, etc.
UDP on the other hand, sends independent datagrams. So there is no specific order in which data is received. UDP is connectionless.
A network computer is identified with two parameters.
IP Address
Port- 16-bit numbers that can range from 0 to 65,535.
Let us create a sample client-server program in Ruby to understand basic networking APIs.
Server-
require 'socket' cosmic_server = TCPServer.open(8080) loop { cosmic_client = cosmic_server.accept cosmic_client.puts "Hello There. I am Cosmic Server" cosmic_client.close }
Client-
require 'socket' cosmic_server = TCPServer.open('localhost', 8080) while data = cosmic_server.gets puts data end cosmic_server.close
The Client receives the message from the local IP address and port 8080.
Serialization is the process that writes an object's data to a stream.
The inverse process of reading the stream into an object is called Deserialization. This concept is useful when you want to preserve and retrieve the object’s state later
For example- (serialization)
class Employee def initialize(empId, empName) @empId = empId @empName = empName end def get_empId return @empId end def get_empName return @empName end end emp = Employee.new(1, "sita") seredObject = Marshal.dump(emp)
The above example has created an Employee class. In this example, we have used the Marshal.dump to serialize the Employee to a binary object.
For example- (deserialization)
class Employee def initialize(empId, empName) @empId = empId @empName = empName end def get_empId return @empId end def get_empName return @empName end end emp = Employee.new(1, "sita") seredObject = Marshal.dump(emp) emp2 = Marshal.load(seredObject) puts "Employee ID = #{emp2.get_empId}" puts "Employee Name = #{emp2.get_empName}"
Ruby allows us to open a file using the File module in different modes- read mode, write mode, append mode, etc. we will explain this with an example of how we can open a file for reading.
For example- (reading)
newFile = File.new("C:/Desktop/new.txt", "r") while ( line = newFile.gets) puts line end newFile.close()
In the above example, we have opened the file and printing the output using “puts.”
For example- (writing).
newFile = File.new("C:/Desktop/godzilla2.txt", "w") newFile.write("hello") newFile.write("Hii") newFile.close()
In the above example, after writing to the file, we have close it using the “close()” function.
Ruby allows us to create and work with threads with the concept of multithreading. It lets us create several threads, that run in parallel and share process CPU and memory. Multiple threads can share memory and communicate with each other. This can significantly speed up your program execution.
Suppose, we need to parse a large CSV file, for that, we can create as many worker threads to do it and speed up time. Also, if we want to run the task as a background operations in a User Interface program, we can create a background thread to do so.
For example- (creating a thread)
def run puts "running thread" end t1 = Thread. new{run()} T1.join
For example- (joining a thread)
def cosmicthread1 puts "hello?" puts "working" end def cosmicthread2 puts "hello2" puts "I = got it?" end def cosmicthread3 puts "Human Knowledge belongs to the World" puts "Like Asprin" end cthread1 = Thread.new{cosmicthread1()} cthread2 = Thread.new{cosmicthread2()} cthread3 = Thread.new{cosmicthread3()} cthread1.join() cthread2.join() cthread3.join()
Using I/O capabilities, we can provide input and get output from the program. Ruby provides API functions, such as gets and puts to work with console input and output.
For example- puts function.
str = "shortcut" puts str j = 10 puts "The value of j is #{j}"
For example- gets function
puts "enter name:- " name = gets puts "Hello #{name}"
def scrub_string str str = str.to_s if !str.is_a?String str = str.gsub(/\W|\_/, "").downcase end def check_palindrome? str str = scrub_string(str) (str.length/2).times do |index_counter| if str[index_counter] != str[-(index_counter + 1)] return false end end true end def check_palindrome? str str = scrub_string(str) str == str.reverse ? true : false end p check_palindrome?("a")
def sum(array) return array.inject(:+) end
class Human
def talk puts "I’m talking" end private def whisper puts "I’m whispering" end end
What is the output of
%i|select reject|.map { |m| array.partition(&odd?)}
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # one line version arr.each { |number| puts number } # multi-line version arr.each do |number| puts number end
def multiple_string(str, n) return str*n end print multiple_string('a', 1),"\n" print multiple_string('a', 2),"\n" print multiple_string('a', 3),"\n" print multiple_string('a', 4),"\n" print multiple_string('a', 5),"\n"
def start_if(str) return str[0, 2] == "if"; end print start_if("ifelse"),"\n" print start_if("endif"),"\n"
Rails is a web application development framework based on the Ruby programming language. It is designed to help developers by making the development work more accessible and streamlined. Rails is a high-level, interpreted programming language compatible with different programming paradigms. Rails, however, is a framework that can be used to build innovative, robust, and secured web applications.
Expect to come across this popular question in the Ruby on Rails interview.
Below are the significant benefits of using RoR for web development.
Below are some disadvantages that need to be considered while working with RoR.
Below are the use cases where RoR is the perfect fit.
Examples of famous applications built on Ruby are-
A staple in Ruby and Rails interview questions, be prepared to answer this one. ORM is the short form for the Object Relational Model that helps connect an application's objects to tables within a relational database management system. It lets you store and access the properties and relationships of the application’s objects from a database without running the SQL statements directly.
ORM is a library that encapsulates the code for manipulating the data without needing (SQL) anymore but uses an object of your language.
False and nil are the built-in data types in Ruby. Both are different and has different meaning.
Nil | FALSE |
---|---|
nil is a NilClass object | false is a FalseClass object, |
not a valid value | is a valid value |
does have a type | is a boolean data type |
Both are different and have a different purposes in ruby on rails. Considering syntactically, strings are the text that is enclosed within the quotation marks, while the symbol is the text that starts with a colon sign.
Ruby symbols are “scalar value objects that you can use as identifiers, mapping immutable strings to fixed internal values.” Symbols are immutable strings that you cannot change.
Symbols are approx 1.7 times faster than Strings. If you use the same symbol multiple times, they will have the same object ID, referring to the same object. While, Strings will be a different object with a unique object ID, referring to different objects.
Rails controller is the logical part of the application. It orchestrates the user's interaction with the views and the model. There are other significant roles of the controller-
C:\ruby\library> ruby script/generate controller Subject.
Notice that we have capitalized the Subject and used the singular form. This command accomplishes several relevant tasks:
It will create the file called app/controllers/subject_controller.rb, witht he following content
class SubjectController < ApplicationController
end
The Controller classes inherit from ApplicationController, which is available in the other file in the controller's folder, called application.rb.
A rails migration is a tool that allows you to alter the application’s database schema. Instead of using SQL scripts, you can use domain-specific language to define the database's modifications. As the code in RoR is database-agnostic, you can easily port the project to another platform. You can roll back and manage the modifications alongside your application source code.
We can use the following command to create a migration.
For this, we can use the rails generates command in the rails command prompt.
Go to start>>Railsinstaller>>command prompt, then root your application directory.
Use the following code.
Rails generate migration record1.
The migration file will convert to camel Case to underscore: record_1.rb with the current date and time, as shown.
The file will be stored in the db directory inside migrate, and that file has a Ruby class defined in it.
This is a frequently asked question in Ruby on Rails basic interview questions. Whenever we create an object, memory is allocated to it. Ruby supports two different types of memory. The first is the malloc heap, where the entire program is included. This memory will be released back to the operating system if the memory is known to be unused by Ruby at the end of a garbage collection.
The second is the Ruby object heap, a subset of the malloc heap that holds the most Ruby objects. If objects are large, they point to the malloc heap. The Ruby heap is consistently monitored and cleaned by the Ruby garbage collector.
Ruby works on the mark and sweep garbage collection algorithm that uses three colors. That marks every object with either white, black, or gray, hence the name tricolor
Each variable in Ruby is declared by placing a special character at the start of the variable name. Variables store some values that can be accessed and used within the program based on their scope.
Below are different types of variables available in Ruby.
Local variables- these are the local variables we can use within the code block where they are declared. We use symbol [a-z] or _
For example-
pi = 3.1415 def valueofpi pi = 3.142 puts "Value of pi inside valueofpi = #{pi}" end valueofpi() puts "Value of pi = #{pi}"
Instance variables- these variables are like Class variables whose values are local to specific instances of an object. We can use the instance variables across methods for any specified instance or object i.e., and instance variables can change from object to object. We use the symbol @.
For example-
class Employee def set_data(empName, empAge) @name = empName @age = empAge end def get_name() return @name end def get_age() return @age end end e1 = Employee.new e1.set_data("rita", 24) e2 = Employee.new e2.set_data("sita", 31) puts "Employee #1, Name = #{e1.get_name()}, Age = #{e1.get_age()}" puts "Employee #2, Name = #{e2.get_name()}, Age = #{e2.get_age()}"
Class variables- these variables starts with @@ sign that are available across different objects. A class variable belongs to the class, and it is a characteristic of a class. They are also known as the global variables within the context of a single class.
For example-
@@no_of_customers = 0
Global variables- always starts with $. Its scope is global, which means we can access it from anywhere in a program.
For example-
$message = "hello" def changeMessage $message = "heh" puts "msg change #{$message}" end puts "changed msg #{$message}" changeMessage()
Load reads and parses files every time during file execution. However, in most cases, developers use the “require” method. But there are some scenarios where we want to use the “load” to pick the latest module changes within the class
Below is the syntax-
load 'filename'
Require is used to read the file from the file system, parse it, save it to the memory, and run it in each place. If you make any changes to the file while the script is running, the “require” will not pick the changes as Ruby will use the file from th memory.
Below is the syntax-
require 'filename'
MVC is the framework that divides any extensive application into three parts.
Working of MVC-
Access modifiers are an important concept of the object-oriented programming language that restricts the visibility of methods and member fields to protect against accidental changes to the code. Regarding access control, Ruby is different from other Object Oriented Programming languages.
We have 3 different access modifiers in Ruby, namely -
Ruby offers a program called ERB, which stands for Embedded Ruby. It is used when you need to directly put the codes associated with Ruby into the HTML files, irrespective of the size and complexity of the codes.
Editors are used to writing code. Ruby supports the usage of various editors. We can choose any editor as per our requirements and with ease.
The active records represent the “M” of the MVC, which is the system layer responsible for representing the business data and logic. It lets you access, create, read, update, and delete the data from the relational database. It is a core part of the MVC design.
Basic functionalities of the active record are-
Gems are used to extend the functionalities of their distributions. Some gems get automatically installed with Ruby installation, while you need to install some explicitly. Also, you can have different versions of the same gems installed in your system.
Execute the following command to get the list of all the gems available.
rvm gemset list
RVM is a command-line tool that allows us to easily install, manage, and work with different ruby environments, from interpreters to sets of gems. The GitHub community maintains RVM through pull requests sent to the project repository. It lets us deploy each project with its own self-contained and dedicated environment.
Below is the basic RVM syntax-
rvm command_options command ruby_to_act_on.
For upgrading the RVM, we use the following command.
rvm get head
Rails bundler offers a constant environment for applications by tracking required gems.
You can use the following command to use the specific bundler.
Gem install bundler. The gem bundler bundles all the suitable gems required by any specific application to work efficiently. Bundling Rails and other dependencies might increase the size by a few megabytes.
Fixtures allow you to organize data that you want to test against and can feed into your unit testing. The fixtures will be created automatically when rails generate any test for the controllers and models. They are just for test purposes, and you cannot access them while running the application.
Typically fixtures are expressed in terms of YAML files.
For example-
# orders.yml payments_equal_line_item_total: # no attributes needed # line_items.yml electric_polisher: order: payments_equal_line_item_total name: 'Electric polisher' price_cents: 400
Each YAML fixture is given a name and is followed by an indented list of key/value pairs in the “key: value” format. A blank line separates records for your viewing pleasure.
The differences below will help you understand where to use strings and symbols.
If the text available is “data,” then use a string. But, if it is code, then use a symbol.
Symbols are not text; they are unique identifiers and are static, such as numbers, bar codes, etc., while, unlike symbols, strings be easily changed.
You can use strings containing the exact text within the code multiple times by creating a new string object. While, for using the symbol, the number of times you do put, it will only create one object and can be reused.
For example-
# Symbols (same id) :foo_bar.object_id # => 2386588 :foo_bar.object_id # => 2386588 # Strings (different ids) "foo_bar".object_id # => 1020 "foo_bar".object_id # => 1040
You can use destroy to delete the record from the rails along with all dependencies. For example, the authors or other details associated with the book will all be deleted if you want to delete a book record.
For example-
$ rails console Loading development environment (Rails 3.2.9) >> book = Book.create(title: 'example) (0.1ms) begin transaction SQL (25.8ms) INSERT INTO "books" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Sun, 18 Nov 2012 15:11:41 UTC +00:00], ["title", "example"], ["updated_at", Sun, 18 Nov 2012 15:11:41 UTC +00:00]] (2.1ms) commit transaction => # >> Book.count (0.3ms) SELECT COUNT(*) FROM "books" => 1 >> book.destroy (0.1ms) begin transaction Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."book_id" = 1 SQL (0.3ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 1]] (3.0ms) commit transaction => # >> Book.count (0.2ms) SELECT COUNT(*) FROM "books" => 0 >>
Objects are the core building blocks of any OOP program. The same goes with Ruby on rails. An object is a combination of data and methods used to communicate through methods. Each object can receive messages, send messages, and process data.
For creating an object. We must define a class, a template for an object describing the state and behavior that the class objects all share. We can create many objects for a class. Objects created at runtime from a class are called instances of that class.
For example-
#!/usr/bin/ruby class Being end b = Being.new //object creation puts b
In ruby, “==” returns true if the two comparison entities are the same. For example, if a=1.
At the same time, “equal” will check if both entities are the same object. For example- a.equal?(b) iff a is the same object as b
These are nonexecutable parts of a program. We can write comments in between our programs for reference purposes. We can write on one line or span multiple lines of comments.
One-liner comment
# one-liner
Multiple line comments
=begin Hello This Is
Multi line comment
=end
Rake is a commonly used task management and build automation tool, allowing users to specify tasks and their related dependencies and group tasks in a namespace. You can also say that rake is the task runner that manages tasks like creating database backup, running tests, and gathering necessary reports. Without a rake, all the tasks will be scattered for all projects. It helps in accessing the tasks centrally.
When we must run the rake task, we must ensure the following.
RubyMine allows running an arbitrary Rake task. For example, we will see how we can run the db:migrate task for migrating a database in the Rails application.
Run a task using Run Anything.
Press ^ twice and type db:migrate in the invoked popup. Select rake db:migrate from the list and press enter.
Go to the main menu, select Tools | Run Rake Task ⌥ R. type g db:migrate in the popup, select db:migrate, and press enter.
Select the required migration version and the environment from the popup. Click OK.
Run a rake text from the editor
Open *.rake file. Click the Run Rake Task button on the gutter next to the required task or Place the caret at the required task name and press. ⌥ ⏎
Take the required action whether to run or debug the task, select Run '<task name>' or Debug '<task name>'. Press enter.
After the task is executed, RubyMine automatically creates a unique profile - a temporary run/debug configuration where we can customize the settings of this configuration.
It's no surprise that this one pops up often in interview questions about Ruby on Rails. You can use the destructive method to alter the state of an object. String, Array, Hash, and others have such methods. The method has two different versions, one with a plain name, the other with the same name, followed by !. The plain version will create a copy of the receiver, make the required change, and return the copy. The other or the “bang” version (with the !) alters the receiver in place.
Rails filters are methods that run either before or after the execution of the controller's action method. You can use this filter method when you want to ensure that a given code block runs with a specified action method called.
There are three filter methods:
Before filters- Rails before filters are executed before the code in the action controller. They are defined at the top of a controller class that calls them. To set it up, you need to call the before_filter method.
For example-
class UserController < ApplicationController before_filter :verify_password def verify_password ... end end
After filters- these filters are executed after the code in action controller executes. Just like before filters, after filters are also defined at the top of a controller class that calls them. We need to use the after_filter method to set it up.
For example-
class PhotoController < ApplicationController after_filter :resize_photo def resize_photo ... end end
Around filters- Rails around filters contain codes that can execute both before and after the execution of the controller's code. They are used when you need both before and after the filter. Implementing around filters is more complex than the other two filters. It is defined by a common class containing both before and after methods.
For example-
class ActionLogger def before(controller) @start_time = Time.new end def after(controller) @end_time = Time.now @elapsed_time = @end_time.to_f - @start_time.to_f @action = controller.action_name table end end
Observers are the simple method, allowing one object to inform a set of objects when its State changes. It is used when a one-to-many relationship exists between the object. If one object gets a notification, another dependent object will also get a notification and update automatically.
Execute the following command to create an observer.
$ rails g observer User
We will explain this with a simple example where we would like to send emails to the user based on their activity status.
class User < Activerecord::Base after_save :send_email private def send_email if status_changed? UserNotificationMailer.account_open_email(self).deliver if status=='created' UserNotificationMailer.account_activated_email(self).deliver if status == 'active' UserNotificationMailer.account_deactivation_email(self).deliver if status =='deactive' end end End
The above code works fine as expected. But there is some issue. Yes, our model job is not to send emails. It will violate the Single Responsibility Principle. So better to implement the observer pattern here.
We will now create a UserObserver class inside the model, which will inherit from ActiveRecord::Observer.
class UserObserver < ActiveRecord::Observer def after_save(record) if record.status_changed? UserNotificationMailer.account_open_email(record).deliver if record.status=='created' UserNotificationMailer.account_activated_email(record).deliver if record.status == 'active' UserNotificationMailer.account_deactivation_email(record).deliver if record.status =='deactive' end end end
Callbacks are commonly used within an object’s life cycle at certain moments, such as after a state change. While using callbacks, you can write codes while creating, saving, updating, deleting, loading, or validating the active record object from the database.
It will give you greater control of data and the applications using it. It changes the usual flow of the code, resulting in complicated debugging and test-making.
There are three types of callbacks.
For using a callback, we need to “register” it at the top of your Model using method specifying the type, such as before_create. We can either pass that method a symbol that corresponds to the method name or write the callback as a block at once.
For example
class User < ActiveRecord::Base before_create do |user| puts "Creating #{user.name}" end after_create :Created private def just_created puts "User Created." end End
In this example, we create a class linked with the database. We call the before_create to check some requirements. Then, call the after_create, which displays the message.
The harness lets you view high-level application metrics collected from various sources and forward them to the collector. You can use any collector that can simply implement the Statsd interface. The harness takes the metrics from ActiveSupport::Notifications and forwards them to the collector.
The harness automatically assumes that the collector can do proper metric aggregation and statistics. For example, using the statsd will calculate the 70th percentile and averages.
You can use a harness specially for very high-traffic applications. Each metric is processed in a separate thread, where the main thread will do just sufficient work.
A symbol is mostly confused with variables, but both are different. Symbols are written like this: “:something,” preceded by a colon. Typical symbols do not contain spaces. So, if you want to create a symbol with multiple words, you need to use underscores, like so: :another_funny_symbol.
//add use cases//
A Proc object encapsulates the code block you can store within a local variable, pass to a method or another Proc, and be called.
For example
square = Proc.new {|x| x**2 } square.call(3) #=> 9 # shorthands: square.(3) #=> 9 square[3] #=> 9
def gen_times(factor) Proc.new {|n| n*factor } # remembers the value of factor now of creation end times3 = gen_times(3) times5 = gen_times(5) times3.call(12) #=> 36 times5.call(5) #=> 25 times3.call(times5.call(4)) #=> 60
count() is an Array class method that returns the total number of elements present within the array. Count uses three different approaches.
Count all: do not require any parameter and will return a count of all the rows.
For example
Person.count # returns the total count of all people
Count using column: pass a column name to count and will return a count of all the rows for that column present.
For example-
Person.count(:age) # returns the total count of all people whose age is present in the database
Count using options will find the row count based on the options.
For example-
Person.count(:conditions => "age > 26") Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN. Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id") # finds the number of rows matching the conditions and joins. Person.count('id', :conditions => "age > 26") # Performs a COUNT(id) Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*')
The size() is a method that is inbuilt into ruby. It returns the size of the set. Simply put, it will return the number of elements present in the set.
For example-
require "set" s1 = Set[11,2,3,4,5] # size method used puts s1.size()
This question is a frequently asked question in Ruby on Rails interview questions. Ruby offers a mechanism for handling exceptions effectively. We need to enclose the code raising or throwing an exception in a begin/end block and use rescue clauses to tell Ruby the types of exceptions we want to handle.
Below is the syntax for exception handling in Ruby
Syntax
begin # - rescue OneTypeOfException # - rescue AnotherTypeOfException # - else # Other exceptions ensure # Always will be executed End
The code within the begin/rescue block is protected. If any error occurs while executing this block, the control will pass to the block between the rescue and end.
For each rescue block, ruby will compare the raised exception for the match and parameters. If the exception name and the name in the rescue parameter are the same, then the block will execute, and the output will be displayed.
For example-
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "file is open" end rescue file = STDIN end print file, "==", STDIN, "\n"
You will get below output-
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Initializers are class instance members that get called whenever a class’s object is created. We must use the name initialize for Initializer.
For example, for an Employee class, we must have an instance method by the name initialize.
Ruby supports two types of initializers.
Parameterless initializer Parameterized initializer For example- parameterless initializer class Employee def initialize @employeeId = 1 @employeeName = "sita" end def setEmployeeId(empId) @employeeId = empId end def setEmployeeName(empName) @employeeName = empName end def getEmployeeId return @employeeId end def getEmployeeName return @employeeName end end
We can use this initializer when we want to set some default values for employee objects. Now create employee object as shown below.
employee1 = Employee.new puts "Employee ID is #{employee1.getEmployeeId()}" puts "Employee Name is #{employee1.getEmployeeName()}"
For example- parameterized initializer
class Employee def initialize(empId, empName) @employeeId = empId @employeeName = empName end def setEmployeeId(empId) @employeeId = empId end def setEmployeeName(empName) @employeeName = empName end def getEmployeeId return @employeeId end def getEmployeeName return @employeeName end end
We can use this initializer when we want to set values for employee attributes while creating the object. Here, we have a parameterized constructor for the Employee class accepting ID and name and assigning it to the Employee object.
Now, create an employee object with parameters as shown below.
employee1 = Employee.new(23, "abc") puts "Employee ID is #{employee1.getEmployeeId()}" puts "Employee Name is #{employee1.getEmployeeName()}"
Functions are a combination of procedural statements that uses functions to execute specific code. For example, a function to perform addition need to declare two variables and add them. A function can return a value to the method that calls that function. If a function does not return a value to the caller, the value is None.
For example-
def add() a = 10 b = 20 return a + b end print add()
Scaffolding refers to the auto-generation of a simple set of a model, views, and controllers, usually for a single table.
Two types of scaffolding are available in Ruby- static and dynamic.
Below is the basic difference between static and dynamic scaffolding.
Dynamic Scaffolding | Static Scaffolding |
---|---|
It generates all content and user interface at runtime. | We need to provide an explicit entry in the command to generate the data with their fields. |
We can create new, delete, and modify methods for usage in your application. | Such a generation does not need to occur. |
Synchronization is not necessary with a database. | It necessitates the migration of the database. |
These are PostgreSQL, DB2, MySQL, SQL, and SQLite.
No doubt, Ruby applications are highly scalable. The significant reasons are: horizontal scaling and is thread-safe. In other words, it will help your application handle more traffic by providing support for additional Ruby processes and adding additional servers.
The Rails console is a command line utility running the Rails applications from the command line, an extension of Ruby IRB. It offers all the facilities of IRB and the ability to auto-load the Rails application environment, including all its classes and components.
A must-know for anyone heading into a Ruby on Rails interview, this question is frequently asked in Ruby Interview Questions. Active Job is a framework to declare and run the jobs on different queueing backends. You can use any job, from regularly scheduled clean-ups to billing charges to sending emails. It is suitable for those tasks that you can split into several small tasks that can be executed simultaneously.
The strong parameters provide an interface that protects the attributes from the end-user assignment. In this case, the Active model does not use the Action Controller parameters for mass assignment until they are explicitly enumerated.
Also, you can mark the parameters as required and flow through a predefined flow to end up as a 400 Bad Request without effort.
Different naming conventions exist for variables, constants, methods, parameters, classes, models, controllers, and modules.
Local variables
example = 0
example_variable = 0
Instance variables
@example
Class variables
@@example
Global variables
$example
CONSTANTS
EXAMPLE_CONSTANT
Methods
def example
End
Parameters
def some_method (example)
end
Classes
ClassExample
Models
Example
Controllers
ExamplesControler
Modules
ModuleExample
Inheritance allows a class to inherit the attributes and behavior of another class. The class that inherits is called the subclass or the child class, and the inherited class is called the superclass or parent class.
Inheritance uses the syntax Subclass < Superclass. If you have C < A, then class C is a child class of A, C inherits from A, or A is the parent of C.
For example,
class Exam def initialize puts "Superclass" end def super_method puts "Method of superclass" end end class Sudo_Placement < Exam def initialize puts "Subclass" end end Exam.new sub_obj = Sudo_Placement.new sub_obj.super_method
Finders in rails help you find specific records with or without any mentioned conditions.
For example-
To find an author with id 50
Author.find(50)
To find authors with id- 20, 30, 40.
author.find([20, 30, 40])
To find the author with the first name as “sita.”
Author.find :all :condition => ["first_name =?", "sita" ]
Available options to be used for finders- :order, :offset, :limit, :group, :joins, :include, :select,: readonly.
If you want to make your application ready for multiple databases, then you need to do that explicitly. Suppose we have an application with a single writer database, and we want to add a new one. Then you must make changes to the database.yml file.
Existing database.yml production: database: my_prim_database adapter: mysql2 username: root password: <%= ENV['ROOT_PASSWORD'] %>
First, add a replica for the existing configuration, and a second database called pet and a replica for that.
New database.yml
production: primary: database: my_prim_database username: root password: <%= ENV['ROOT_PASSWORD'] %> adapter: mysql2 primary_replica: database: my_prim_database username: root_readonly password: <%= ENV['ROOT_READONLY_PASSWORD'] %> adapter: mysql2 replica: true animals: database: my_pet_database username: pet_root password: <%= ENV['PET_ROOT_PASSWORD'] %> adapter: mysql2 migrations_paths: db/pet_migrate animals_replica: database: my_pet_database username: pet_readonly password: <%= ENV['PET_READONLY_PASSWORD'] %> adapter: mysql2 replica: true
Note
Rails::Engine lets you wrap a specific Rails application or a subset of functionality to share it with other applications or within a more extensive packaged application. Every Rails::Application is just an engine allowing simple features and application sharing.
//Add code examples//
It offers you a framework that compresses JavaScript and CSS assets. You can use it to write these assets in other languages and pre-processors such as CoffeeScript, Sass, and ERB. Using this, you can automatically combine your assets with assets from other gems.
You can implement the asset pipeline using the sprockets-rails gem enabled by default. To disable it while creating a new application, you must pass the --skip-asset-pipeline option.
One of the most frequently posed Ruby interview questions, be ready for it. The closure is a function or a code block with variables bound to the environment from which the closure is called. The closure is used as a variable that you can assign to another variable or pass to any function as an argument.
You can define a closure block in one scope and call it in a different scope.
Closure can recognize the variable available within its scope at the creation time and, while calling it, can access the variable even if they are not in the current scope.
Examples of closure in ruby are- Blocks, procs, and lambda.
Blocks are the simplest form of closure, a code piece enclosed between braces {} or do…end.
You can pass more than one variable to the block.
You can use a yield statement to call a block within a method with a value.
It does not have a specific name.
Below is the syntax for creating a block.
block_name { #statements_to_be_executed } Using do…end block_name do #statement-1 #statement-2 . End
For example-
arr = [10, 11, 13, 41, 59] arr.each do | item | puts item End
The forEach() method allows you to loop through each element of an array/object. The forEach() method takes a callback function as an argument invoked for each array element. It is like the for loop but without a return value.
The map() method loops through each element of an array/object. The map() method takes a callback function as an argument that is invoked for each array element. It is like the forEach() method but returns a new array.
Below is the syntax for the map.
array = ["a", "b", "c"]
array.map { |string| string.upcase }
# ["A", "B", "C"]
First, we will have an array. It could be a hash or range. Then we will call a map with a block. It will return a new array with the results. The result will not change, but you can use the map to change the original array.
For example-
Doubling the numbers of an array.
array = [1,2,3]
array.map { |n| n * 2 }
# [2, 4, 6]
Converting string to numbers.
array = ["11", "21", "5"]
array.map { |str| str.to_i }
# [11, 21, 5]
Indexing values with the “with_index” method.
array = %w(a b c)
array.map.with_index { |ch, idx| [ch, idx] }
# [["a", 0], ["b", 1], ["c", 2]]
Lambdas are procs that have distinguishing factors. They are considered the “regular” methods in two ways: they enforce the number of arguments that need to be passed when called, and they use "normal" returns.
When calling a lambda that expects an argument without one, or if you pass an argument to a lambda that does not expect it, an ArgumentError. Will be raised.
irb> lambda (a) { a }.call ArgumentError: wrong number of arguments (given 0, expected 1) from (irb):8:in `block in irb_binding' from (irb):8 from /Users/jeff/.asdf/installs/ruby/2.3.0/bin/irb:11:in `<main>'
Also, for a lambda, the return keyword is same as it is for a method. When calling a proc, the program yields control of the code block. So, if the proc returns, the current scope returns. If a proc is called inside a function and calls return, the function immediately returns.
def return_from_proc a = Proc.new { return 10 }.call puts "not printed." end
The above function will yield control to the proc, so when it returns, the function returns. Calling the function in this example will never print the output and return 10. So we use lambda.
def return_from_lambda a = lambda { return 20 }.call puts "The lambda returned #{a}, and this will be printed." End
When using a lambda, it will be printed. Calling return in the lambda is like calling return in a method, so the “a” variable is populated with “20,” and the line is printed to the console.
With hashes, we can store data as key-value pairs. You can retrieve and modify data using the key.
For example-
countryCapitals = {} countryCapitals["India"] = "Delhi" countryCapitals["United States"] = "D.C." countryCapitals["United Kingdom"] = "London" puts "Count is = #{countryCapitals.length}" # Using Subscript to query the dictionary for a key and get the value. puts "Capital of India is = #{countryCapitals['India']}" # iterate the hash using each countryCapitals.each do |key, value| puts "#{key} => #{value}" end # if the hash contains NYC as a key. puts "ContainsKey - NYC?: #{countryCapitals.key?("NYC")}" # if the dictionary contains London as a value. puts "ContainsValue - D.C.?: #{countryCapitals.has_value?("London")}" # remove an entry from the dictionary. countryCapitals.delete("India") # Print the hash
puts countryCapitals
Computer systems are connected via networks. Two commonly used protocols in a network.
TCP - Transmission Control Protocol.
UDP - User Datagram Protocol.
Network protocol implementations for TCP come under the TCPSocket class. TCP protocol provides same-order communication, which is useful for other protocols like HTTP, SecureFTP, etc.
UDP on the other hand, sends independent datagrams. So there is no specific order in which data is received. UDP is connectionless.
A network computer is identified with two parameters.
IP Address
Port- 16-bit numbers that can range from 0 to 65,535.
Let us create a sample client-server program in Ruby to understand basic networking APIs.
Server-
require 'socket' cosmic_server = TCPServer.open(8080) loop { cosmic_client = cosmic_server.accept cosmic_client.puts "Hello There. I am Cosmic Server" cosmic_client.close }
Client-
require 'socket' cosmic_server = TCPServer.open('localhost', 8080) while data = cosmic_server.gets puts data end cosmic_server.close
The Client receives the message from the local IP address and port 8080.
Serialization is the process that writes an object's data to a stream.
The inverse process of reading the stream into an object is called Deserialization. This concept is useful when you want to preserve and retrieve the object’s state later
For example- (serialization)
class Employee def initialize(empId, empName) @empId = empId @empName = empName end def get_empId return @empId end def get_empName return @empName end end emp = Employee.new(1, "sita") seredObject = Marshal.dump(emp)
The above example has created an Employee class. In this example, we have used the Marshal.dump to serialize the Employee to a binary object.
For example- (deserialization)
class Employee def initialize(empId, empName) @empId = empId @empName = empName end def get_empId return @empId end def get_empName return @empName end end emp = Employee.new(1, "sita") seredObject = Marshal.dump(emp) emp2 = Marshal.load(seredObject) puts "Employee ID = #{emp2.get_empId}" puts "Employee Name = #{emp2.get_empName}"
Ruby allows us to open a file using the File module in different modes- read mode, write mode, append mode, etc. we will explain this with an example of how we can open a file for reading.
For example- (reading)
newFile = File.new("C:/Desktop/new.txt", "r") while ( line = newFile.gets) puts line end newFile.close()
In the above example, we have opened the file and printing the output using “puts.”
For example- (writing).
newFile = File.new("C:/Desktop/godzilla2.txt", "w") newFile.write("hello") newFile.write("Hii") newFile.close()
In the above example, after writing to the file, we have close it using the “close()” function.
Ruby allows us to create and work with threads with the concept of multithreading. It lets us create several threads, that run in parallel and share process CPU and memory. Multiple threads can share memory and communicate with each other. This can significantly speed up your program execution.
Suppose, we need to parse a large CSV file, for that, we can create as many worker threads to do it and speed up time. Also, if we want to run the task as a background operations in a User Interface program, we can create a background thread to do so.
For example- (creating a thread)
def run puts "running thread" end t1 = Thread. new{run()} T1.join
For example- (joining a thread)
def cosmicthread1 puts "hello?" puts "working" end def cosmicthread2 puts "hello2" puts "I = got it?" end def cosmicthread3 puts "Human Knowledge belongs to the World" puts "Like Asprin" end cthread1 = Thread.new{cosmicthread1()} cthread2 = Thread.new{cosmicthread2()} cthread3 = Thread.new{cosmicthread3()} cthread1.join() cthread2.join() cthread3.join()
Using I/O capabilities, we can provide input and get output from the program. Ruby provides API functions, such as gets and puts to work with console input and output.
For example- puts function.
str = "shortcut" puts str j = 10 puts "The value of j is #{j}"
For example- gets function
puts "enter name:- " name = gets puts "Hello #{name}"
def scrub_string str str = str.to_s if !str.is_a?String str = str.gsub(/\W|\_/, "").downcase end def check_palindrome? str str = scrub_string(str) (str.length/2).times do |index_counter| if str[index_counter] != str[-(index_counter + 1)] return false end end true end def check_palindrome? str str = scrub_string(str) str == str.reverse ? true : false end p check_palindrome?("a")
def sum(array) return array.inject(:+) end
class Human
def talk puts "I’m talking" end private def whisper puts "I’m whispering" end end
What is the output of
%i|select reject|.map { |m| array.partition(&odd?)}
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # one line version arr.each { |number| puts number } # multi-line version arr.each do |number| puts number end
def multiple_string(str, n) return str*n end print multiple_string('a', 1),"\n" print multiple_string('a', 2),"\n" print multiple_string('a', 3),"\n" print multiple_string('a', 4),"\n" print multiple_string('a', 5),"\n"
def start_if(str) return str[0, 2] == "if"; end print start_if("ifelse"),"\n" print start_if("endif"),"\n"
To ace your Ruby on Rails advanced interview questions, you must know these useful tips and tricks o achieve better.
Acing your Ruby programming interview or Ruby on Ruby on Rails senior developer interview questions is always tricky. The major thing, if you understand the requirement for the RoR developer, then you know where to start. Make sure to cover the following aspects while preparing.
With the following drafted Ruby on Rails interview questions and answers, you can quickly answer the questions related to top ruby job positions like
Prepare well with these Ruby interview questions and answers and crack your upcoming and scheduled interview at organizations like
Whether you are applying for Ruby technical interview questions or an interview for freshers, you must work on your Ruby on Rails advanced interview questions and can expect the following.
To help you ease your journey of preparing for your upcoming ruby programming interview, we have curated some ruby programming interview questions that will help you understand the in-and-out of Ruby on Rails. To learn more about RoR, you can go for Computer Programming training.
If you are applying for job positions like Ruby Engineer, Senior Ruby on Rails Engineer, Full Stack Ruby Developer, Senior Ruby Developer, and others. In that case, this guide is the way to go. Deep dive into the detailed knowledge of Ruby on Rails which will surely help you crack your interviews with excellence.
With different sections for freshers, intermediate, and advanced, along with simple and logical programming questions that you must know and have handy, you will find it easier to stay focused for your interviews. Each section comes with questions and answers based on different proficiency levels.
So, go through this article, and good luck!
Submitted questions and answers are subjecct to review and editing,and may or may not be selected for posting, at the sole discretion of Knowledgehut.
Get a 1:1 Mentorship call with our Career Advisor
By tapping submit, you agree to KnowledgeHut Privacy Policy and Terms & Conditions