require 'dry/core/deprecations' require 'rom/initializer' require 'rom/repository/class_interface' require 'rom/repository/session' module ROM # Abstract repository class to inherit from # # A repository provides access to composable relations and commands. # Its job is to provide application-specific data that is already materialized, so that # relations don't leak into your application layer. # # Typically, you're going to work with Repository::Root that is configured to # use a single relation as its root, and compose aggregates and use changesets and commands # against the root relation. # # @example # rom = ROM.container(:sql, 'sqlite::memory') do |conf| # conf.default.create_table(:users) do # primary_key :id # column :name, String # end # # conf.default.create_table(:tasks) do # primary_key :id # column :user_id, Integer # column :title, String # end # # conf.relation(:users) do # associations do # has_many :tasks # end # end # end # # class UserRepo < ROM::Repository[:users] # def users_with_tasks # aggregate(:tasks).to_a # end # end # # user_repo = UserRepo.new(rom) # user_repo.users_with_tasks # # @see Repository::Root # # @api public class Repository extend ClassInterface extend Initializer extend Dry::Core::ClassAttributes # @!method self.auto_struct # Get or set auto_struct setting # # When disabled, rom structs won't be created # # @overload auto_struct # Return auto_struct setting value # @return [TrueClass,FalseClass] # # @overload auto_struct(value) # Set auto_struct value # @return [Class] defines :auto_struct auto_struct true # @!method self.auto_struct # Get or set struct namespace defines :struct_namespace # @!method self.relation_reader # Get or set relation reader module # @return [RelationReader] defines :relation_reader struct_namespace ROM::Struct # @!attribute [r] container # @return [ROM::Container] The container used to set up a repo param :container, allow: ROM::Container # @!attribute [r] struct_namespace # @return [Module,Class] The namespace for auto-generated structs option :struct_namespace, default: -> { self.class.struct_namespace } # @!attribute [r] auto_struct # @return [Boolean] The container used to set up a repo option :auto_struct, default: -> { self.class.auto_struct } # @!attribute [r] relations # @return [RelationRegistry] The relation proxy registry used by a repo attr_reader :relations # Initializes a new repo by establishing configured relation proxies from # the passed container # # @param container [ROM::Container] The rom container with relations and optional commands # # @api private def initialize(container, options = EMPTY_HASH) super @relations = {} end # Open a database transaction # # @example commited transaction # user = transaction do |t| # create(changeset(name: 'Jane')) # end # # user # # => # # # @example with a rollback # user = transaction do |t| # changeset(name: 'Jane').commit # t.rollback! # end # # user # # nil # # @api public def transaction(&block) container.gateways[:default].transaction(&block) end # Return a string representation of a repository object # # @return [String] # # @api public def inspect %(#<#{self.class} struct_namespace=#{struct_namespace} auto_struct=#{auto_struct}>) end # Start a session for multiple changesets # # TODO: this is partly done, needs tweaks in changesets so that we can gather # command results and return them in a nice way # # @!visibility private # # @api public def session(&block) session = Session.new(self) yield(session) transaction { session.commit! } end end end require 'rom/repository/root'