lib/rom/sql/plugin/associates.rb in rom-sql-3.6.4 vs lib/rom/sql/plugin/associates.rb in rom-sql-4.0.0.alpha1

- old
+ new

@@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'rom/sql/associations' +require "rom/sql/associations" module ROM module SQL module Plugin # Make a command that automaticaly sets FK attribute on input tuples @@ -14,61 +14,94 @@ # @api private def initialize(name, relation, opts) @name = name @assoc = relation.associations[name] - @opts = { assoc: assoc, keys: assoc.join_keys } + @opts = {assoc: assoc, keys: assoc.join_keys} @opts.update(parent: opts[:parent]) if opts[:parent] end def after? assoc.is_a?(SQL::Associations::ManyToMany) end def to_hash - { associate: opts } + {associate: opts} end end # @api private def self.included(klass) klass.class_eval do extend ClassMethods include InstanceMethods - defines :associations + setting :associations, default: {}, reader: true - associations Hash.new - option :associations, default: -> { self.class.associations } + option :configured_associations, default: -> { EMPTY_ARRAY } end super end # @api public module ClassMethods + # @api private + def create_class(relation:, rel_meta: {}, parent_relation: nil, **, &block) + klass = super + + if relation && rel_meta[:combine_type] + setup_associates(klass, relation, parent_relation) + end + + klass + end + + # Sets up `associates` plugin for a given command class and relation + # + # @param [Class] klass The command class + # @param [Relation] relation The relation for the command + # + # @api private + def setup_associates(klass, relation, parent_relation) + assoc_name = + if relation.associations.key?(parent_relation) + parent_relation + else + singular_name = relation.inflector.singularize(parent_relation).to_sym + singular_name if relation.associations.key?(singular_name) + end + + if assoc_name + klass.associates(assoc_name) + else + klass.associates(parent_relation) + end + end + # @see ROM::Command::ClassInterface.build # # @api public def build(relation, **options) command = super configured_assocs = command.configured_associations associate_options = command.associations.map { |(name, opts)| next if configured_assocs.include?(name) + AssociateOptions.new(name, relation, opts) }.compact before_hooks = associate_options.reject(&:after?).map(&:to_hash) after_hooks = associate_options.select(&:after?).map(&:to_hash) - command. - with(configured_associations: configured_assocs + associate_options.map(&:name)). - before(*before_hooks). - after(*after_hooks) + command + .with(configured_associations: configured_assocs + associate_options.map(&:name)) + .before(*before_hooks) + .after(*after_hooks) end # Set command to associate tuples with a parent tuple using provided keys # # @example @@ -94,11 +127,13 @@ if associations.key?(name) raise ArgumentError, "#{name} association is already defined for #{self.class}" end - associations(associations.merge(name => options)) + associations[name] = options + + self end end module InstanceMethods # Set fk on tuples from parent tuple @@ -107,10 +142,12 @@ # @param [Hash] parent The parent tuple with its pk already set # # @return [Array<Hash>] # # @api public + # + # rubocop:disable Lint/UnusedMethodArgument def associate(tuples, curried_parent = nil, assoc:, keys:, parent: curried_parent) result_type = result output_tuples = case assoc @@ -135,9 +172,10 @@ } end result_type == :one ? output_tuples[0] : output_tuples end + # rubocop:enable Lint/UnusedMethodArgument # Return a new command with the provided association # # @param [Symbol, Relation::Name] name The name of the association #