Ruby Core
Q1: Proc vs. lambda?
A lambda is strict (enforces argument count, non-local return). A Proc is lenient (assigns nil to missing arguments, local return from definition scope).
Q2: == vs. eql? vs. equal??
equal? checks object identity (same memory address). == checks value equality (commonly overridden). eql? is stricter than == (used for Hash keys).
Q3: attr_reader vs. attr_writer vs. attr_accessor?
attr_reader creates a getter. attr_writer creates a setter. attr_accessor creates both.
Q4: extend vs. include?
include makes module methods available as instance methods. extend makes module methods available as class methods.
Q5: nil vs. false?
Both are falsy. false is the boolean value. nil means “no value.”
Q6: freeze vs. const_set?
freeze prevents modification of an object’s state (immutability). const_set defines a new constant at runtime.
Q7: Ruby Struct vs. OpenStruct?
Struct defines a class with a fixed set of attributes (better performance). OpenStruct allows dynamic, arbitrary attributes on the fly (more flexible).
Q8: private vs. protected methods?
private can only be called implicitly (without a receiver, or on self). protected can be called on self or any other instance of the defining class/subclass.
&. (Ruby 2.3+) is the native operator that safely calls a method or returns nil if the receiver is nil (preferred). try is a method that does the same.
Q10: Hash merge vs. merge!?
merge returns a new hash containing the combined key-value pairs. merge! (or update) modifies the original hash in place (mutates it).
Q11: initialize vs. new (in object creation)?
new is the class method that creates a new object instance. initialize is the instance method that is automatically called by new to set up the object’s initial state.
Q12: Class variable (@@) vs. instance variable (@)?
@ is an instance variable, unique to each object. @@ is a class variable, shared by the class itself and all its subclasses.
Q13: String vs. Symbol?
A String is mutable and a new object is created every time. A Symbol is immutable, and the same object is reused across the entire program (more efficient as hash keys).
Q14: self in a class definition vs. in an instance method?
In a class body, self refers to the class itself. Inside an instance method, self refers to the current instance of the class.
Q15: super vs. super()?
super calls the superclass method with the same arguments passed to the current method. super() calls the superclass method with no arguments.
Q16: Module prepend vs. include?
include inserts the module above the class in the ancestor chain. prepend inserts the module below the class, allowing module methods to override class methods.
Q17: Class method (self.method) vs. class method defined via class << self?
Functionally identical. self.method is simpler for one-off methods. class << self is used for grouping multiple class methods or complex meta-programming.
Q18: Parentheses in method calls?
Parentheses are optional when there is no ambiguity. They are required when ambiguity exists (e.g., passing the result of one method as an argument to another) or when defining arguments for the method.
Q19: tap vs. yield_self (then)?
tap executes a block and returns the original receiver. yield_self (or then) executes a block and returns the result of the block (useful for chaining transformations).
Q20: raise vs. fail?
They are aliases for the same method used to raise an exception. Ruby style guides often prefer raise for code flow control and fail for assertions/validation checks.
Q21: alias vs. alias_method?
alias is a Ruby keyword used to create an alias for a method in the current scope. alias_method is a Module instance method used programmatically, often in meta-programming (e.g., when overriding methods and calling the original).
Q22: Module vs. Class?
A Class can be instantiated and represents a concrete object type. A Module cannot be instantiated and is used to group related methods, acting as a namespace or a mixin.
Active Record
Q1: find vs. find_by?
find takes an ID and raises RecordNotFound if not found. find_by takes a condition and returns the record or nil.
Q2: where vs. find_by?
where returns an ActiveRecord::Relation (collection, lazily evaluated). find_by returns a single object (nil if none, executed immediately).
Q8: select vs. pluck?
select retrieves full AR objects with limited columns. pluck retrieves an array of raw values, bypassing AR instantiation (faster).
Q3: new vs. create?
new creates object in memory, does not hit DB. create creates object and attempts to save immediately (#save is called).
Q4: save vs. save!?
save returns true/false. save! raises an exception on failure (RecordInvalid).
Q5: destroy vs. delete (single object)?
destroy runs callbacks (e.g., dependents). delete skips callbacks and performs a direct SQL DELETE.
Q6: destroy_all vs. delete_all (relation)?
destroy_all instantiates each object and runs callbacks. delete_all performs a single bulk SQL DELETE without callbacks.
Q7: has_many vs. has_one?
has_many is a one-to-many relationship. has_one is a one-to-one relationship.
Q8: includes vs. eager_load (N+1)?
includes can use separate queries or LEFT OUTER JOIN. eager_load always forces a single LEFT OUTER JOIN.
Q9: belongs_to vs. has_one (FK location)?
belongs_to is on the child model (FK is on the child’s table). has_one is on the parent model (FK is on the associated table).
Q10: validates vs. validates_with?
validates is a macro for built-in, simple validations. validates_with applies a custom, reusable validator class object.
Q11: has_many through vs. has_and_belongs_to_many (HABTM)?
has_many through uses an explicit model (join model) for the association. HABTM uses a simple join table without a dedicated model.
Q12: touch vs. manual timestamp update?
touch is a method that updates the updated_at and updated_on attributes of a record without running validations or callbacks. Manual updates run full save logic.
Q13: after_create vs. after_save?
after_create runs only when a new record is inserted into the database. after_save runs after both creation and updating of a record.
Q14: Counter cache vs. manual count?
A counter cache is a special column on the parent table that Active Record automatically increments/decrements, providing O(1) lookups. Manual count performs a costly O(N) database query on the association.
Q15: update_attribute vs. update?
update_attribute(name, value) changes and saves a single attribute, skipping validations and mass-assignment protection. update(attributes) changes multiple attributes and runs validations and callbacks.
Q16: validates_presence_of vs. validates :attr, presence: true?
They are equivalent. The second (validates :attr, presence: true) is the modern, preferred syntax as it allows all validations to be grouped into a single call.
Q17: maximum vs. max?
maximum is a database query method (SELECT MAX(...)) that operates on the ActiveRecord::Relation and is more efficient. max is a Ruby Enumerable method that loads all records into memory first and then finds the maximum value.
Q18: Polymorphic association vs. standard belongs_to?
A polymorphic association allows a model to belong to more than one other model on a single association, using two columns (_type and _id). A standard belongs_to links to only one model.
Q19: before_validation vs. before_save?
before_validation runs before validation logic. before_save runs after successful validation, just before the record is persisted.
Q20: first vs. limit(1)?
first retrieves the first record based on the default scope (often sorted by ID). limit(1) simply limits the result set to one and doesn’t guarantee sorting unless explicitly chained with an order clause.
Q21: increment! vs. increment?
increment updates the attribute in memory but does not save the record. increment! updates the attribute in memory and immediately saves the record, bypassing validation.
Q22: default_scope vs. explicit scope?
default_scope is automatically applied to every query on the model (can be confusing). An explicit scope must be called manually when needed.
Q23: Implicit vs. explicit transaction?
An implicit transaction (e.g., using save!) is started and committed by Active Record internally. An explicit transaction (ActiveRecord::Base.transaction do...end) allows a block of code to be treated as a single atomic unit.
Blocks & Procs
Q1: Block vs. Proc?
A Block is non-object code attached to a method. A Proc is a block converted into a reusable object (Proc class).
Q2: yield vs. call?
yield executes an implicit block passed to a method. call executes an explicit block object (Proc or lambda).
Q3: map vs. each?
map returns a new array of results from the block. each returns the original collection (used for side effects).
Q4: inject vs. reduce?
They are aliases for the exact same method, used to combine elements into a single return value.
Controllers
Q1: render vs. redirect_to?
render stays in the current request cycle (URL unchanged). redirect_to issues a new HTTP request (URL changes).
session data is primarily for server/encrypted client storage across requests. cookies are explicitly stored client-side and can have expiration dates.
Q3: before_action vs. around_action?
before_action runs before the action. around_action wraps the action, running code both before and after the action yields control.
Q4: flash vs. flash.now?
flash stores message for the next request (used with redirect). flash.now stores message for the current request (used with render).
Q5: Strong Parameters permit vs. require?
require ensures a key is present in the params hash (raises error if missing). permit filters which attributes are allowed for mass assignment.
Q6: current_user vs. User.find(…)?
current_user is a helper method, usually cached (runs DB query once per request). Direct User.find(...) runs a query every time.
Q7: params vs. session?
params hold data for the current HTTP request (URL, query string, form data). session holds data that persists across multiple requests for a single user.
Q8: respond_to vs. explicit rendering?
respond_to blocks allow the controller to choose the appropriate response format (HTML, JSON, XML) based on the client’s request header. Explicit rendering uses a single, fixed format.
Q9: rescue_from vs. begin/rescue?
rescue_from is used in the controller to globally handle specific exceptions for all actions. begin/rescue is used for handling exceptions locally within a single method block.
Q10: Filtering params vs. strong_parameters?
Manually filtering params is insecure as it’s easy to miss an attribute. Strong Parameters is the official Rails mechanism, enforcing explicit whitelisting of attributes for mass assignment.
Q11: head vs. render nothing: true (deprecated)?
head is the clean, official way to send an empty response body with a specific HTTP status code (e.g., head :ok). The old render nothing: true syntax is deprecated.
Q12: Fat Controller vs. Skinny Controller?
A Fat Controller contains too much business logic, data manipulation, and complex rendering decisions. A Skinny Controller delegates most logic to models, services, or form objects, focusing only on HTTP request/response flow.
Views
Q1: form_for vs. form_with?
form_with is the modern unified approach; it defaults to AJAX. form_for and form_tag are older, separate methods.
Q2: link_to vs. raw HTML tag?
link_to is a helper that generates the <a> tag and can resolve URLs from model objects, and safely handle non-GET methods (POST, DELETE).
Q3: (ERB) <%= vs. <%# vs. <%?
<%= executes code and outputs the result. <%# is a comment. <% executes code but does not output the result.
Q4: partial vs. layout?
A layout is the main wrapper template for the shared structure. A partial is a reusable snippet of code rendered within a view or layout.
Q5: current_page? vs. comparing request.path?
current_page? is a safe, robust helper method to check the current URL. Comparing raw request.path is fragile and less descriptive.
Q6: distance_of_time_in_words vs. time_ago_in_words?
distance_of_time_in_words takes two Time objects and calculates the difference. time_ago_in_words takes one Time object and calculates the difference from the current time.
Q7: raw vs. html_safe?
html_safe marks a string as safe and tells Rails not to escape it (dangerous if not controlled). raw is a helper that returns the result of calling html_safe on its input.
Q8: content_tag vs. raw HTML tag?
content_tag is a helper for programmatically generating HTML tags (e.g., <div>, <a>), making dynamic view code cleaner and safer.
Q9: stylesheet_link_tag vs. raw tag?
stylesheet_link_tag handles asset fingerprinting, precompilation, and environment-specific linking, ensuring correct paths in production.
Q10: render partial: `name` vs. render ‘name’?
They are equivalent if the string doesn’t contain a slash. render 'name' is the shorthand, relying on Rails to infer the context (partial). render partial: 'name' is explicit and often cleaner for readability.
Routing
Q1: resource vs. resources?
resources generates seven standard RESTful routes (including index). resource generates six routes (omits index) for singular resources.
Q2: member vs. collection routes?
Member routes act on a specific resource (requires an ID, e.g., /photos/1/preview). Collection routes act on the entire collection of resources (no ID, e.g., /photos/search).
Q3: get vs. match?
get registers a route that responds only to the HTTP GET verb. match can register a route for multiple verbs, often used with the via: option or in legacy code.
Q4: Nesting resources vs. flat resources?
Nesting creates hierarchical, user-friendly URLs (e.g., /posts/1/comments/2) and enforces access control. Flat resources are simpler but lose the relationship context in the URL.
Testing
Q1: Unit Test vs. Integration Test?
Unit Test isolates and tests a small component (method, class). Integration Test verifies multiple components (controller, view, model) work together.
Q2: Fixtures vs. Factories (FactoryBot)?
Fixtures use static YAML data. Factories dynamically generate flexible test data using Ruby code.
Q3: bin/rails test vs. rspec?
bin/rails test uses the default Minitest framework. rspec is a popular external BDD (Behavior-Driven Development) framework.
Q4: Controller test vs. Request test?
Controller tests isolate the controller logic, allowing stubs and mocks. Request tests (the modern standard) test the full stack, simulating a user request against the entire application.
Q5: Mocks vs. Stubs?
A Stub is an object that returns pre-determined values when its methods are called (used for state verification). A Mock is an object with expectations set on it to verify that specific methods were called (used for behavior verification).
Database
Q1: SQL vs. NoSQL (in Rails context)?
SQL uses Active Record for structured schemas. NoSQL requires specific gems (like Mongoid) and bypasses Active Record’s relational assumptions.
Q2: db:schema:dump format sql vs. ruby?
ruby (schema.rb) is database-agnostic. sql (structure.sql) is required for non-Active Record specific database features (triggers, procedures).
Q3: Migrations change vs. up/down methods?
The change method is preferred and automatically figures out how to reverse the migration. up/down methods require you to manually specify both the forward and backward logic.
Q4: index vs. unique: true index?
A standard index speeds up data retrieval. A unique: true index also ensures that no two rows in the table can have the same value for that column.
Configuration
Q5: development vs. production environment?
development enables quick iteration, no caching, extensive logging. production enables caching, minimal logging, speed optimization.
Q6: CLI rake vs. rails CLI?
rake is for general Ruby tasks (DB migrations, testing). rails is for Rails-specific tasks (generators, server, console).
Q7: Dependencies bundle install vs. bundle update?
bundle install installs exact versions from Gemfile.lock. bundle update installs the latest permissible versions and updates Gemfile.lock.
Q8: ActiveSupport Time.now vs. Time.current (in Rails)?
Time.now uses system time zone. Time.current uses the application’s configured time zone (guaranteeing consistency, usually UTC).
Q9: config.eager_load in dev vs. prod?
In production it’s true (loads all code at boot). In development it’s false (allows code reloading without restarting).
Q10: Scopes scope vs. class method?
scope creates a class method that must return an ActiveRecord::Relation object and is typically for simple chaining. A class method is more flexible and can return anything (though it often returns a Relation).
Q11: Gems require vs. gem (in Gemfile)?
gem is used in the Gemfile to declare a dependency for Bundler. require is used in Ruby code to load a library into memory at runtime.
Q12: config/secrets.yml vs. Environment variables?
secrets.yml (or credentials.yml.enc in modern Rails) stores environment-specific settings. Environment variables (e.g., set via shell or OS) are the most secure way to store highly sensitive information like API keys.
Security
Q1: XSS vs. CSRF?
XSS (Cross-Site Scripting) involves injecting malicious client-side scripts into web pages. CSRF (Cross-Site Request Forgery) involves tricking a user’s browser into executing unwanted actions on a web application where they are authenticated.
Assets
Q1: javascript_include_tag vs. Asset Pipeline //= require?
javascript_include_tag creates the HTML <script> tag. //= require is a manifest directive that tells the Asset Pipeline which files to concatenate.
Q2: Sprockets vs. Webpacker?
Sprockets is the older Rails asset management system, primarily for simple JS/CSS concatenation. Webpacker (now jsbundling-rails) integrates modern JS tooling (like Webpack, Esbuild) for handling complex JavaScript dependencies.
Q3: Fingerprinting vs. caching?
Fingerprinting (appending a hash to filenames, e.g., app-d90c9.js) ensures that asset updates force browsers to download the new version (cache busting). Caching is the browser storing the file for faster future access.
Jobs
Q1: ActiveJob vs. Sidekiq/DelayedJob?
ActiveJob is the framework interface layer. Sidekiq/DelayedJob are the specific background job backends that execute the jobs.
Q2: perform vs. perform_later vs. perform_now?
perform is the instance method inside the job that contains the business logic. perform_now executes the job synchronously immediately. perform_later queues the job to run asynchronously in the background.
Miscellaneous
Q1: ActiveSupport Hash vs. HashWithIndifferentAccess?
A standard Hash requires exact key type (String or Symbol). HashWithIndifferentAccess (used in params) allows access using either a String or a Symbol.
Conclusion
This comprehensive guide covers 100 essential Ruby on Rails concepts that every developer should understand. Whether you’re preparing for an interview, brushing up on fundamentals, or learning Rails for the first time, these questions and answers provide a solid foundation for understanding the framework’s core principles and best practices.
Happy coding! 🚀
Comments (0)