lib/rom/sql/plugin/associates.rb in rom-sql-0.7.0 vs lib/rom/sql/plugin/associates.rb in rom-sql-0.8.0

- old
+ new

@@ -1,5 +1,7 @@ +require 'rom/support/deprecations' + module ROM module SQL module Plugin # Make a command that automaticaly sets FK attribute on input tuples # @@ -10,10 +12,25 @@ klass.extend(ClassMethods) super end module InstanceMethods + attr_reader :assoc, :__registry__ + + # @api private + def initialize(*) + super + @__registry__ = relation.__registry__ + assoc_name, assoc_opts = self.class.associations[0] + @assoc = + if assoc_opts.any? + assoc_opts[:key] + else + relation.associations[assoc_name] + end + end + # Set fk on tuples from parent tuple # # @param [Array<Hash>, Hash] tuples The input tuple(s) # @param [Hash] parent The parent tuple with its pk already set # @@ -21,17 +38,40 @@ # # @overload SQL::Commands::Create#execute # # @api public def execute(tuples, parent) - fk, pk = association[:key] + input_tuples = + case assoc + when Array + fk, pk = assoc - input_tuples = with_input_tuples(tuples).map { |tuple| - tuple.merge(fk => parent.fetch(pk)) - } + input_tuples = with_input_tuples(tuples).map { |tuple| + tuple.merge(fk => parent.fetch(pk)) + } - super(input_tuples) + super(input_tuples) + when Association::ManyToMany + new_tuples = super(tuples) + + join_tuples = assoc.associate(__registry__, new_tuples, parent) + join_relation = assoc.join_relation(__registry__) + join_relation.multi_insert(join_tuples) + + pk, fk = __registry__[assoc.target] + .associations[assoc.source] + .combine_keys(__registry__).to_a.flatten + + pk_extend = { fk => parent[pk] } + + new_tuples.map { |tuple| tuple.update(pk_extend) } + when Association + input_tuples = with_input_tuples(tuples).map { |tuple| + assoc.associate(relation.__registry__, tuple, parent) + } + super(input_tuples) + end end end module ClassMethods # @api private @@ -60,19 +100,20 @@ # @param [Symbol] name The name of associated table # @param [Hash] options The options # @option options [Array] :key The association keys # # @api public - def associates(name, options) - if associations.include?(name) + def associates(name, options = {}) + if associations.map(&:first).include?(name) raise ArgumentError, "#{name} association is already defined for #{self.class}" end - option :association, reader: true, default: -> _command { options } + option :association, reader: true, default: {} + include InstanceMethods - associations << name + associations << [name, options] end end end end end