Skip to content
Ruby on RailsRuby on Rails Web Development: Hints/Tricks & more
  • RoR Framework
  • RoR Github
  • RoR Developers
  • Contact

Rails caching management

  • Post author By Mary Frann
  • Post date August 30, 2022
  • Categories In Ruby on Rails

All communication methods are built around caching, which keeps the results of recent requests available for future operations. The cache is shared between different methods. For example:

author.books # get books from database

author.books.size # use the cached copy of the books

author.books.empty? # use the cached copy of the books

But what if you want to reload the cache because the data may have been modified by another part of the application? Just call reload on the connection:

author.books # get books from database

author.books.size # use the cached copy of the books

author.books.reload.empty? # discard the cached copy of the books

                             # and access the database again

Name Collision Prevention

You are not free to choose any name for your connections. Since creating a relationship adds a method with that name to the model, it would be a bad idea to give the relationship a name already used as an instance method of ActiveRecord::Base. The link method will then override the base method and anything will stop working. For example, attributes or connection are bad names for relationships.

schema update

Links are very useful, but not magical. You are responsible for maintaining your database schema in accordance with the links. In practice, this means two things, depending on what type of links you are creating. For belongs_to relationships, you need to create foreign keys, and for has_and_belongs_to_many relationships, you need to create a suitable join table.

Creating Foreign Keys for belongs_to Relationships

When you declare a belongs_to relationship, you need to create foreign keys, if necessary. For example, consider this model:

classBook < ApplicationRecord

  belongs_to :author

end

This declaration needs to create a suitable foreign key on the books table:

class CreateBooks < ActiveRecord::Migration[5.0]

  def change

    create_table :books do |t|

      t.datetime :published_at

      t.string :book_number

      t.integer :author_id

    end

  end

end

If you are creating a relationship after you have already created the underlying model, you must remember to create an add_column migration to provide the required foreign key.

It is good practice to add an index on the foreign key to improve query performance, and a constraint on the foreign key to ensure referential integrity of the data:

class CreateBooks < ActiveRecord::Migration[5.0]

  def change

    create_table :books do |t|

      t.datetime :published_at

      t.string :book_number

      t.integer :author_id

    end

    add_index :books, :author_id

    add_foreign_key :books, :authors

  end

end

Create join tables for has_and_belongs_to_many relationships

If you have created a has_and_belongs_to_many relationship, you must create a join table. If a join table name is not explicitly specified using the :join_table option, Active Record creates a name using the alphabetical order of the class names. Therefore, the join between the author and book models will default to the value of the table name “authors_books” since “a” comes before “b” in alphabetical order.

WARNING: Precedence between model names is calculated using the <=> operator for String. This means that if the strings are of different lengths and they are equal in their short part, then the longer string is treated as having a higher lexical precedence than the shorter one. For example, one would expect the tables “paperboxes” and “papers” to create a join table “papers_paper_boxes” because the name “paper_boxes” is longer, but would actually generate a table named “paper_boxes_papers” (because the underscore character “\” is lexicographically smaller than “s” in normal encoding).

Whatever the name, you must manually generate the join table in the appropriate migration. For example, consider these links:

class Assembly < ApplicationRecord

  has_and_belongs_to_many :parts

end

class Part<ApplicationRecord

  has_and_belongs_to_many :assemblies

end

Now we need to write a migration to create the assemblies_parts table. This table must be created without a primary key:

class CreateAssembliesPartsJoinTable < ActiveRecord::Migration[5.0]

  def change

    create_table :assemblies_parts, id: false do |t|

      t.integer :assembly_id

      t.integer :part_id

    end

    add_index :assemblies_parts, :assembly_id

    add_index :assemblies_parts, :part_id

  end

end

We are passing id: false to create_table since this table does not represent a model. This is necessary for the connection to work correctly. If you see strange behavior in the has_and_belongs_to_many relationship, such as malformed model IDs, or ID conflict exceptions, you most likely forgot to remove the primary key.

You can also use the create_join_table method

class CreateAssembliesPartsJoinTable < ActiveRecord::Migration[5.0]

  def change

    create_join_table :assemblies, :parts do |t|

      t.index :assembly_id

      t.index :part_id

    end

  end

end

Link Scope Control

By default, links only look for objects within the scope of the current module. This is important when you declare Active Record models inside a module. For example:

module MyApplication

  module business

    class Supplier < ApplicationRecord

      has_one :account

    end

    class Account < ApplicationRecord

      belongs_to :supplier

    end

  end

end

This will work since both the Supplier and Account classes are defined within the same scope. But the following won’t work because Supplier and Account are defined in different scopes:

module MyApplication

  module business

    class Supplier < ApplicationRecord

      has_one :account

    end

  end

  module Billing

    class Account < ApplicationRecord

      belongs_to :supplier

    end

  end

end

To link a model to a model in a different namespace, you must specify the fully qualified class name in the link declaration:

Bilateral Relations

It is normal for relationships to work in two directions, requiring a declaration in two different models:

classAuthor<ApplicationRecord

  has_many:books

end

classBook < ApplicationRecord

  belongs_to :author

end

Active Record will attempt to automatically determine that the two models form a bidirectional relationship based on the name of the relationship. This way, Active Record will only load one copy of the Author object, making your application more efficient and preventing inconsistent data:

a = Author.first

b = a.books.first

a.first_name == b.author.first_name # => true

a.first_name = ‘David’

a.first_name == b.author.first_name # => true

Active Record supports autodetection for most associations with standard names. However, Active Record will not automatically detect bidirectional links containing any of the following options:

:conditions

:through

:polymorphic

:class_name

:foreign_key

For example, consider the following model declarations:

  • Tags developer ruby on rails, install ruby on rails ubuntu, is ruby on rails dead, node js vs ruby on rails, ruby on rails, ruby on rails creator about bitcoin, ruby on rails creator backpedals about, ruby on rails creator backpedals bitcoin, ruby on rails developer salary, ruby on rails development company, ruby on rails example, ruby on rails install, ruby on rails logo, ruby on rails vs python, what is ruby on rails used for
  • Open Facebook in a new tab
  • Open Twitter in a new tab
  • Open Instagram in a new tab
  • Open LinkedIn in a new tab
  • Open Pinterest in a new tab
© 2023  Proudly powered by WordPress