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