Rails study questions Flashcards Preview

Rails > Rails study questions > Flashcards

Flashcards in Rails study questions Deck (96):

What part of MVC is Active Record?

M- the model


What is the model layer of the system responsible for?

Representing business data and logic.


What does Active Record facilitate?

The creation and use of business objects whose data requires persistent storage to a database.


What is the Active Record pattern a description of?

An Object Relational Mapping system.


What are two features of objects in Active Record?

Objects carry both persistent dat and behavior which operates on that data.


How will ensuring data access logic as part of the object educate users?

It will educate users on how to write to and read from the database.


What is Object Relational Mapping?

ORM is a technique that connects the rich objects of an application to tables in a relational database management system.


What are two advantages of using ORM?

You don't have to write SQL statements directly and you need less overall database access code.


What are five mechanisms Active Record gives us?

1. Represent models and their data.
2. Represent associations between these models.
3. Represent inheritance hierarchies through related models.
4. Validate models before they get persisted to the database.
5. Perform database operations in an object-oriented fashion.


What is a configuration advantage of creating Active Record models?

Explicit configuration is needed only in those cases where you can't follow the standard convention.


What is optimistic locking?

It allows multiple users to access the same records for edits, and assumes a minimum of conflicts with the data. It does this by checking whether another process has made changes to a record since it was opened.


What does a lock_version column name do?

It adds optimistic locking to a model.


What does a "type" column name do?

Specifies that the model uses Single Table Inheritance.


What is Single Table inheritance?

Inheritance via storing the name of the class in a column that is named "type" by default.


What does an "(association_name)_type" column name do?

Stores the type for polymorphic associations.


What does an "(table_name)_count" column name do?

Used to cache the number of belonging objects on associations.


What does creating an ActiveRecord::Base model allow you to map?

The columns of each row in a database table with the attributes of the instances of your model.


What are three methods you can use to override naming conventions?

self.table_name =

set_fixture_class table_name: ClassName

self.primary_key =


What is the difference between create and new?

The new method will return a new object while create will return the object and save it to the database.


What does CRUD stand for?

Create, Read, Update, Delete


What happens if a block is provided to new or create?

if a block is provided, both create and new will yield the new object to that block for initialization:


What is the method to delete an Active Record object?



What is a useful method for updating several records in bulk?



What does validation allow?

Active Record allows you to validate the state of a model before it gets written into the database.


What is the difference between what "save" returns vs. what "save!" returns when Active Record validation fails?

class User < ApplicationRecord
validates :name, presence: true

user = User.new
user.save # => false
user.save! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank


What do Active Record callbacks allow you to do?

Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on


What are migrations?

Rails provides a domain-specific language for managing a database schema called migrations.


Where are migrations stored?

Migrations are stored in files which are executed against any database that Active Record supports using rake.


What does rails keep track of re: migrations?

Rails keeps track of which files have been committed to the database and provides rollback features. To actually create the table, you'd run rails db:migrate and to roll it back, rails db:rollback.


How do migrations work differently on databases that support transactions and those that do not?

On databases that support transactions with statements that change the schema, migrations are wrapped in a transaction. If the database does not support this then when a migration fails the parts of it that succeeded will not be rolled back. You will have to rollback the changes that were made by hand.


What benefit does using a Ruby DSL for migrations provide?

You don't have to write SQL by hand, allowing your schema and changes to be database independent.


What is a macro?

A single instruction that expands automatically into a set of instructions to perform a particular task.


What is a database transaction?

A sequence of operations performed as a single logical unit of work. A logical unit of work must exhibit four properties, called the atomicity, consistency, isolation and durability (ACID) properties, to qualify as a transaction.


What is an example of using 'reversible' to do something that active record doesn't know how to reverse?

class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def change
reversible do |dir|
change_table :products do |t|
dir.up { t.change :price, :string }
dir.down { t.change :price, :integer }


What is an alternative to using reversible?

You can use up and down instead of change.

class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def up
change_table :products do |t|
t.change :price, :string

def down
change_table :products do |t|
t.change :price, :integer


What happens if a migration name is of the form "AddXXXToYYY" or "RemoveXXXFromYYY" and is followed by a list of column names

a migration containing the appropriate add_column and remove_column statements will be created.

$ bin/rails generate migration AddPartNumberToProducts part_number:string

will generate

class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string


How do you add an index on a new column from the console?

$ bin/rails generate migration AddPartNumberToProducts part_number:string:index


What happens f the migration name is of the form "CreateXXX" and is followed by a list of column names and types

a migration creating the table XXX with the columns listed will be generated.


How does a migration accept references?

Also, the generator accepts column type as references (also available as belongs_to). For instance:
$ bin/rails generate migration AddUserRefToProducts user:references


class AddUserRefToProducts < ActiveRecord::Migration[5.0]
def change
add_reference :products, :user, foreign_key: true

This migration will create a user_id column and appropriate index.


How do you produce a join table from the console?

$ bin/rails g migration CreateJoinTableCustomerProduct customer product

which generates

class CreateJoinTableCustomerProduct < ActiveRecord::Migration[5.0]
def change
create_join_table :customers, :products do |t|
# t.index [:customer_id, :product_id]
# t.index [:product_id, :customer_id]


How are type modifiers passed directly on the command line?

They are enclosed by curly braces and follow the field type:

For instance, running:

$ bin/rails generate migration AddDetailsToProducts 'price:decimal{5,2}' supplier:references{polymorphic}
will produce a migration that looks like this

class AddDetailsToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :price, :decimal, precision: 5, scale: 2
add_reference :products, :supplier, polymorphic: true


What do you do if you need to pass database-specific options to an ActiveRecord migration?

false. If you need to pass database specific options you can place an SQL fragment in the :options option. For example:

create_table :products, options: "ENGINE=BLACKHOLE" do |t|
t.string :name, null: false

will append ENGINE=BLACKHOLE to the SQL statement used to create the table (when using MySQL or MariaDB, the default is ENGINE=InnoDB).


What is the comment option?

Also you can pass the :comment option with any description for the table that will be stored in database itself and can be viewed with database administration tools, such as MySQL Workbench or PgAdmin III.


Which adapters currently support comments?

the mySQL and postGRES adapters.


What does the migration method create_join_table do?

The migration method create_join_table creates an HABTM (has and belongs to many) join table.


How do you override null false in the create_join_table command?

create_join_table :products, :categories, column_options: { null: true }


How do you change the default name of a join table?

create_join_table :products, :categories, table_name: :categorization


How can you add indices to a join table?

create_join_table also accepts a block, which you can use to add indices (which are not created by default) or additional columns:

create_join_table :products, :categories do |t|
t.index :product_id
t.index :category_id


What are some examples of column modifiers?

limit Sets the maximum size of the string/text/binary/integer fields.
precision Defines the precision for the decimal fields, representing the total number of digits in the number.
scale Defines the scale for the decimal fields, representing the number of digits after the decimal point.
polymorphic Adds a type column for belongs_to associations.
null Allows or disallows NULL values in the column.
default Allows to set a default value on the column. Note that if you are using a dynamic value (such as a date), the default will only be calculated the first time (i.e. on the date the migration is applied).
index Adds an index for the column.
comment Adds a comment for the column.


How can you specifically change a not null constraint or default values of a column?

Besides change_column, the change_column_null and change_column_default methods are used specifically to change a not null constraint and default values of a column.

change_column_null :products, :name, false
change_column_default :products, :approved, from: true, to: false


What are methods to add or remove a foreign key?



What method can you use to execute arbitrary SQL?

If the helpers provided by Active Record aren't enough you can use the execute method to execute arbitrary SQL:

Product.connection.execute("UPDATE products SET price = 'free' WHERE 1=1")


What makes remove_column reversible?

remove_column is reversible if you supply the column type as the third argument. Provide the original column options too, otherwise Rails can't recreate the column exactly when rolling back:

remove_column :posts, :slug, :string, null: false, default: '', index: true


What should you raise in your down block if your migration is irreversible?



What happens when you specify a target version when running migrations?

If you specify a target version, Active Record will run the required migrations (change, up, down) until it has reached the specified version. The version is the numerical prefix on the migration's filename. For example, to migrate to version 20080906120000 run:

$ bin/rails db:migrate VERSION=20080906120000


What does the db:schema:dump task do?

It is invokes by running the db:migrate task and will update your db/schema.rb file to match the structure of your database.


What can you do if you need to undo several migrations?

you can provide a STEP parameter:

$ bin/rails db:rollback STEP=3


What does the rails db:setup task do?

The rails db:setup task will create the database, load the schema and initialize it with the seed data.


What does the rails db:reset task do?

The rails db:reset task will drop the database and set it up again. This is functionally equivalent to rails db:drop db:setup.


How do you change the environment a migration is run against?

By default running bin/rails db:migrate will run in the development environment. To run migrations against another environment you can specify it using the RAILS_ENV environment variable while running the command. For example to run migrations against the test environment you could run:

$ bin/rails db:migrate RAILS_ENV=test


How do you make Active Record not output anything?

If you want Active Record to not output anything, then running rails db:migrate
VERBOSE=false will suppress all output.


What are three methods that allow you to control the output of a migration?

suppress_messages: Takes a block as an argument and suppresses any output generated by the block.

say: Takes a message argument and outputs it as is. A second boolean argument can be passed to specify whether to indent or not.

say_with_time: Outputs text along with how long it took to run its block. If the block returns an integer it assumes it is the number of rows affected.


What are the two ways to dump the schema?

There are two ways to dump the schema. This is set in config/application.rb by the config.active_record.schema_format setting, which may be either :sql or :ruby.


What happens regarding the database when you deploy a new instance of an app?

There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.

For example, this is how the test database is created: the current development database is dumped (either to db/schema.rb or db/structure.sql) and then loaded into the test database.


What is a limitation of db/schema.rb

There is however a trade-off: db/schema.rb cannot express database specific items such as triggers, stored procedures or check constraints. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this, then you should set the schema format to :sql.


What is a disadvantage of using the :sql schema format?

Using the :sql schema format will prevent loading the schema into a RDBMS other than the one used to create it.


Where does intelligence belong in the Active Record model?

The Active Record way claims that intelligence belongs in your models, not in the database. As such, features such as triggers or constraints, which push some of that intelligence back into the database, are not heavily used.


What is the main purpose of Rails' migration feature?

The main purpose of Rails' migration feature is to issue commands that modify the schema using a consistent process.


How is a has_many :through association often used?

A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.


What does a has_and_belongs_to_many association do?

A has_and_belongs_to_many association creates a direct many-to-many connection with another model, with no intervening model. For example, if your application includes assemblies and parts, with each assembly having many parts and each part appearing in many assemblies, you could declare the models this way:

class Assembly < ApplicationRecord
has_and_belongs_to_many :parts

class Part < ApplicationRecord
has_and_belongs_to_many :assemblies


When should you use has_many vs. has_and_belongs_to_many?

The simplest rule of thumb is that you should set up a has_many :through relationship if you need to work with the relationship model as an independent entity. If you don't need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship (though you'll need to remember to create the joining table in the database).

You should use has_many :through if you need validations, callbacks or extra attributes on the join model.


What is a polymorphic association?

A slightly more advanced twist on associations is the polymorphic association. With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model. Here's how this could be declared:

class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true

class Employee < ApplicationRecord
has_many :pictures, as: :imageable

class Product < ApplicationRecord
has_many :pictures, as: :imageable
You can think of a polymorphic belongs_to declaration as setting up an interface that any other model can use. From an instance of the Employee model, you can retrieve a collection of pictures: @employee.pictures.


How do you set up a polymorphic interface in a model?

If you have an instance of the Picture model, you can get to its parent via @picture.imageable. To make this work, you need to declare both a foreign key column and a type column in the model that declares the polymorphic interface:

class CreatePictures < ActiveRecord::Migration[5.0]
def change
create_table :pictures do |t|
t.string :name
t.integer :imageable_id
t.string :imageable_type

add_index :pictures, [:imageable_type, :imageable_id]
This migration can be simplified by using the t.references form:

class CreatePictures < ActiveRecord::Migration[5.0]
def change
create_table :pictures do |t|
t.string :name
t.references :imageable, polymorphic: true, index: true


How do you model a self join?

his situation can be modeled with self-joining associations:

class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee",
foreign_key: "manager_id"

belongs_to :manager, class_name: "Employee"
With this setup, you can retrieve @employee.subordinates and @employee.manager.

In your migrations/schema, you will add a references column to the model itself.

class CreateEmployees < ActiveRecord::Migration[5.0]
def change
create_table :employees do |t|
t.references :manager, index: true


What are some things you should look out for in order to make efficient use of Active Record associations?

Controlling caching
Avoiding name collisions
Updating the schema
Controlling association scope
Bi-directional associations


Active Record supports automatic identification for most associations with standard names. However, AR will not automatically identify bi-directional associations that contain which options?



How do you explicitly declare bi-directional associations?

Active Record provides the :inverse_of option so you can explicitly declare bi-directional associations:

class Author < ApplicationRecord
has_many :books, inverse_of: 'writer'

class Book < ApplicationRecord
belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'


Where do associations looks for objects by default?

By default, associations look for objects only within the current module's scope. This can be important when you declare Active Record models within a module. For example:

module MyApplication
module Business
class Supplier < ApplicationRecord
has_one :account

class Account < ApplicationRecord
belongs_to :supplier


How do you associate a model with a model in a different namespace?

To associate a model with a model in a different namespace, you must specify the complete class name in your association declaration:

module MyApplication
module Business
class Supplier < ApplicationRecord
has_one :account,
class_name: "MyApplication::Billing::Account"

module Billing
class Account < ApplicationRecord
belongs_to :supplier,
class_name: "MyApplication::Business::Supplier"


What five methods does the declaring class automatically gain when you declare a belongs_to association?

build_association(attributes = {})
create_association(attributes = {})
create_association!(attributes = {})
In all of these methods, association is replaced with the symbol passed as the first argument to belongs_to. For example, given the declaration:

class Book < ApplicationRecord
belongs_to :author
Each instance of the Book model will have these methods:



How do you override association caching behavior?

If the associated object has already been retrieved from the database for this object, the cached version will be returned. To override this behavior (and force a database read), call #reload on the parent object.

@author = @book.reload.author


What options does the belongs_to association support?



What does the :autosave option do?

If you set the :autosave option to true, Rails will save any loaded members and destroy members that are marked for destruction whenever you save the parent object.


What does the counter_cache option do?

The :counter_cache option can be used to make finding the number of belonging objects more efficient.

class Book < ApplicationRecord
belongs_to :author
class Author < ApplicationRecord
has_many :books
With these declarations, asking for the value of @author.books.size requires making a call to the database to perform a COUNT(*) query. To avoid this call, you can add a counter cache to the belonging model:

class Book < ApplicationRecord
belongs_to :author, counter_cache: true
class Author < ApplicationRecord
has_many :books
With this declaration, Rails will keep the cache value up to date, and then return that value in response to the size method.


what are the :dependent options?

:destroy causes the associated objects to also be destroyed.
:delete_all causes the associated objects to be deleted directly from the database (callbacks are not executed).
:nullify causes the foreign keys to be set to NULL (callbacks are not executed).
:restrict_with_exception causes an exception to be raised if there are associated records.
:restrict_with_error causes an error to be added to the owner if there are associated objects.


What does the :touch option do?

If you set the :touch option to true, then the updated_at or updated_on timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:


How can you use #includes?

You can use the includes method to specify second-order associations that should be eager-loaded when this association is used.


Is collection.where lazily loaded?

Yes. The collection.where method finds objects within the collection based on the conditions supplied but the objects are loaded lazily meaning that the database is queried only when the object(s) are accessed.

@available_books = @author.books.where(available: true) # No query yet
@available_book = @available_books.first # Now the database will be queried


What does the collection_singular_ids method do?


The collection_singular_ids method returns an array of the ids of the objects in the collection.

@book_ids = @author.book_ids collection_singular_ids=(ids)

The collection_singular_ids= method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate. The changes are persisted to the database.


What does the :as option indicate?

A polymorphic association.


What does the :source_type option do?

The :source_type option specifies the source association type for a has_many :through association that proceeds through a polymorphic association.


What does the extending method do?

The extending method specifies a named module to extend the association proxy.


What does the limit method do?

The limit method lets you restrict the total number of objects that will be fetched through an association.


What does the offset method do?

The offset method lets you specify the starting offset for fetching objects via an association. For example, -> { offset(11) } will skip the first 11 records.


Why should you not use include? to ensure uniqueness?

Note that checking for uniqueness using something like include? is subject to race conditions. Do not attempt to use include? to enforce distinctness in an association. For instance, using the article example from above, the following code would be racy because multiple users could be attempting this at the same time:

person.articles << article unless person.articles.include?(article)


What should you do if you want to make sure that, upon insertion, all of the records in the persisted association are distinct?

If you want to make sure that, upon insertion, all of the records in the persisted association are distinct (so that you can be sure that when you inspect the association that you will never find duplicate records), you should add a unique index on the table itself. For example, if you have a table named readings and you want to make sure the articles can only be added to a person once, you could add the following in a migration:

add_index :readings, [:person_id, :article_id], unique: true