Repositories serve as a crucial component of the persistence layer within an application. Their primary purpose is to encapsulate the functionality provided by Rails' Active Record and expose a subset of simplified methods for querying and persisting data. By utilizing repositories, we can isolate Active Record operations to this subset, ensuring that other layers of the application only interact with the desired queries and methods.

In the context of our application, the Bike Repository now handles all operations that were previously managed by the Bike Record. This includes tasks such as finding, creating, and deleting records. By consolidating these responsibilities within the repository, we establish a clear separation of concerns and promote maintainability and flexibility within our codebase.

require_relative "../db/records/bike"
require "active_record"

module Bikes
  class RecordNotFound < StandardError
  end

  class Repository
    def initialize
      setup_database
    end

    def all
      Db::Records::Bike.all
    end

    def create(name:)
      Db::Records::Bike.create(name: name)
    end

    def find(id:)
      Db::Records::Bike.find(id)
    rescue ActiveRecord::RecordNotFound
      raise RecordNotFound.new
    end

    def update(id:, params:)
      record = find(id: id)
      record.update(params)
      record
    end

    def delete(id:)
      record = find(id: id)
      record.destroy!
    end

    private

    def setup_database
      ActiveRecord::Base.configurations = YAML.load_file("db/configuration.yml")
      ActiveRecord::Base.establish_connection(ENV["RACK_ENV"].to_sym)
    end
  end
end

It’s worth noting that the term “Records” is now used to refer to Active Record objects. This change is reflected by moving the previous Bike class from the “db” directory to “db/records” and placing it within the appropriate module. This reorganization further enhances the modularity and organization of our codebase.

require "active_record"

module Db
  module Records
    class Bike < ActiveRecord::Base
      has_many :components
    end
  end
end

However, it’s important to acknowledge that Active Record is not completely encapsulated at this stage. The repository still returns Record objects that are relied upon by controllers and views. These Record objects serve multiple purposes within the application. In certain actions, such as “new” and “edit,” they represent user input, capturing the data entered by the user. On the other hand, in actions like “index” and “show,” they embody the actual persisted entities within the system. Additionally, Record objects hold any validation errors that may occur during attempted persistence operations.

By introducing the BikeRepository, we achieve several benefits:

  1. Modularity: The repository isolates the database interactions, making it easier to understand, test, and modify the persistence layer without affecting other parts of the application.
  2. Separation of Concerns: The repository separates the concerns of querying and persisting data from the business logic and the user interface. This promotes a cleaner architecture and enhances code organization.
  3. Testability: By abstracting the database interactions behind a repository interface, we can easily write unit tests for the other layers of the application. We can mock the repository’s methods to simulate different scenarios and verify the behavior of the calling code.
  4. Flexibility: Repositories provide a flexible interface that can adapt to changing requirements. If the underlying data storage needs to be replaced or modified, the repository can be updated accordingly without affecting other parts of the application.

In conclusion, repositories play a vital role in simplifying data persistence in the applications. By encapsulating Active Record within a subset of methods, repositories provide a focused and intuitive interface for querying and persisting data. They promote modularity, separation of concerns, testability, and flexibility. When used effectively, repositories contribute to a more maintainable, scalable, and robust application architecture. The whole code where I added repositories into the app is on github