vorpal 1.0.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +73 -26
  3. data/lib/vorpal/aggregate_mapper.rb +13 -2
  4. data/lib/vorpal/aggregate_traversal.rb +9 -8
  5. data/lib/vorpal/config/association_config.rb +84 -0
  6. data/lib/vorpal/config/belongs_to_config.rb +35 -0
  7. data/lib/vorpal/config/class_config.rb +71 -0
  8. data/lib/vorpal/config/configs.rb +54 -0
  9. data/lib/vorpal/config/foreign_key_info.rb +23 -0
  10. data/lib/vorpal/config/has_many_config.rb +38 -0
  11. data/lib/vorpal/config/has_one_config.rb +35 -0
  12. data/lib/vorpal/config/main_config.rb +68 -0
  13. data/lib/vorpal/db_loader.rb +25 -22
  14. data/lib/vorpal/driver/postgresql.rb +42 -6
  15. data/lib/vorpal/dsl/config_builder.rb +26 -73
  16. data/lib/vorpal/dsl/configuration.rb +139 -42
  17. data/lib/vorpal/dsl/defaults_generator.rb +1 -1
  18. data/lib/vorpal/engine.rb +27 -13
  19. data/lib/vorpal/exceptions.rb +4 -0
  20. data/lib/vorpal/identity_map.rb +7 -2
  21. data/lib/vorpal/loaded_objects.rb +57 -14
  22. data/lib/vorpal/util/array_hash.rb +22 -8
  23. data/lib/vorpal/util/hash_initialization.rb +1 -1
  24. data/lib/vorpal/version.rb +1 -1
  25. data/vorpal.gemspec +4 -5
  26. metadata +18 -78
  27. data/.editorconfig +0 -13
  28. data/.envrc +0 -4
  29. data/.gitignore +0 -16
  30. data/.rspec +0 -1
  31. data/.ruby-version +0 -1
  32. data/.travis.yml +0 -18
  33. data/.yardopts +0 -1
  34. data/Appraisals +0 -18
  35. data/Gemfile +0 -4
  36. data/Rakefile +0 -39
  37. data/bin/appraisal +0 -29
  38. data/bin/rake +0 -29
  39. data/bin/rspec +0 -29
  40. data/docker-compose.yml +0 -19
  41. data/gemfiles/rails_5_1.gemfile +0 -11
  42. data/gemfiles/rails_5_1.gemfile.lock +0 -101
  43. data/gemfiles/rails_5_2.gemfile +0 -11
  44. data/gemfiles/rails_5_2.gemfile.lock +0 -101
  45. data/gemfiles/rails_6_0.gemfile +0 -9
  46. data/gemfiles/rails_6_0.gemfile.lock +0 -101
  47. data/lib/vorpal/configs.rb +0 -296
  48. data/spec/acceptance/vorpal/aggregate_mapper_spec.rb +0 -910
  49. data/spec/helpers/codecov_helper.rb +0 -7
  50. data/spec/helpers/db_helpers.rb +0 -69
  51. data/spec/helpers/profile_helpers.rb +0 -26
  52. data/spec/integration/vorpal/driver/postgresql_spec.rb +0 -42
  53. data/spec/integration_spec_helper.rb +0 -29
  54. data/spec/performance/vorpal/performance_spec.rb +0 -305
  55. data/spec/unit/vorpal/configs_spec.rb +0 -117
  56. data/spec/unit/vorpal/db_loader_spec.rb +0 -103
  57. data/spec/unit/vorpal/dsl/config_builder_spec.rb +0 -18
  58. data/spec/unit/vorpal/dsl/defaults_generator_spec.rb +0 -75
  59. data/spec/unit/vorpal/identity_map_spec.rb +0 -62
  60. data/spec/unit/vorpal/loaded_objects_spec.rb +0 -22
  61. data/spec/unit/vorpal/util/string_utils_spec.rb +0 -25
  62. data/spec/unit_spec_helper.rb +0 -1
@@ -0,0 +1,23 @@
1
+ require 'equalizer'
2
+
3
+ module Vorpal
4
+ module Config
5
+ # @private
6
+ class ForeignKeyInfo
7
+ include Equalizer.new(:fk_column, :fk_type_column, :fk_type)
8
+
9
+ attr_reader :fk_column, :fk_type_column, :fk_type, :polymorphic
10
+
11
+ def initialize(fk_column, fk_type_column, fk_type, polymorphic)
12
+ @fk_column = fk_column
13
+ @fk_type_column = fk_type_column
14
+ @fk_type = fk_type
15
+ @polymorphic = polymorphic
16
+ end
17
+
18
+ def polymorphic?
19
+ @polymorphic
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ require 'vorpal/config/configs'
2
+
3
+ module Vorpal
4
+ module Config
5
+ # @private
6
+ # Object association terminology:
7
+ # - All object associations are uni-directional
8
+ # - The end that holds the association is the 'Owner' and the end that
9
+ # is referred to is the 'Associate' or 'Associates'
10
+ #
11
+ # Relational association terminology:
12
+ # - Local end: has FK
13
+ # - Remote end: has no FK
14
+ #
15
+ class HasManyConfig
16
+ include Util::HashInitialization
17
+ include RemoteEndConfig
18
+
19
+ attr_reader :name, :owned, :fk, :fk_type, :associated_class, :unique_key_name
20
+ attr_accessor :association_config
21
+
22
+ def get_associated(owner)
23
+ owner.send(name)
24
+ end
25
+
26
+ def associate(owner, associates)
27
+ if get_associated(owner).nil?
28
+ owner.send("#{name}=", [])
29
+ end
30
+ get_associated(owner) << associates
31
+ end
32
+
33
+ def pretty_name
34
+ "#{@class_config.domain_class.name} has_many :#{name}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require 'vorpal/config/configs'
2
+
3
+ module Vorpal
4
+ module Config
5
+ # @private
6
+ # Object association terminology:
7
+ # - All object associations are uni-directional
8
+ # - The end that holds the association is the 'Owner' and the end that
9
+ # is referred to is the 'Associate' or 'Associates'
10
+ #
11
+ # Relational association terminology:
12
+ # - Local end: has FK
13
+ # - Remote end: has no FK
14
+ #
15
+ class HasOneConfig
16
+ include Util::HashInitialization
17
+ include RemoteEndConfig
18
+
19
+ attr_reader :name, :owned, :fk, :fk_type, :associated_class, :unique_key_name
20
+ attr_accessor :association_config
21
+
22
+ def get_associated(owner)
23
+ owner.send(name)
24
+ end
25
+
26
+ def associate(owner, associate)
27
+ owner.send("#{name}=", associate)
28
+ end
29
+
30
+ def pretty_name
31
+ "#{@class_config.domain_class.name} has_one :#{name}"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,68 @@
1
+ require 'vorpal/exceptions'
2
+ require 'vorpal/config/association_config'
3
+
4
+ module Vorpal
5
+ module Config
6
+ # @private
7
+ class MainConfig
8
+ def initialize
9
+ @class_configs = []
10
+ end
11
+
12
+ def config_for(clazz)
13
+ config = @class_configs.detect { |conf| conf.domain_class == clazz }
14
+ raise Vorpal::ConfigurationNotFound.new("No configuration found for #{clazz}") unless config
15
+ config
16
+ end
17
+
18
+ def config_for_db_object(db_object)
19
+ @class_configs.detect { |conf| conf.db_class == db_object.class }
20
+ end
21
+
22
+ def add_class_config(class_config)
23
+ @class_configs << class_config
24
+ end
25
+
26
+ def initialize_association_configs
27
+ association_configs = {}
28
+ @class_configs.each do |config|
29
+ (config.has_ones + config.has_manys).each do |association_end_config|
30
+ associated_class_config = config_for(association_end_config.associated_class)
31
+ association_end_config.set_class_config(config)
32
+
33
+ association_config = build_association_config(association_configs, associated_class_config, association_end_config.fk, association_end_config.fk_type)
34
+ association_config.remote_end_config = association_end_config
35
+ association_config.add_remote_class_config(config)
36
+ association_end_config.association_config = association_config
37
+ end
38
+
39
+ config.belongs_tos.each do |association_end_config|
40
+ associated_class_configs = association_end_config.associated_classes.map(&method(:config_for))
41
+
42
+ association_config = build_association_config(association_configs, config, association_end_config.fk, association_end_config.fk_type)
43
+ association_config.local_end_config = association_end_config
44
+ association_config.add_remote_class_config(associated_class_configs)
45
+ association_end_config.association_config = association_config
46
+ end
47
+ end
48
+
49
+ association_configs.values.each do |association_config|
50
+ association_config.local_class_config.local_association_configs << association_config
51
+ association_config.validate
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def build_association_config(association_configs, local_config, fk, fk_type)
58
+ association_config = AssociationConfig.new(local_config, fk, fk_type)
59
+ if association_configs[association_config]
60
+ association_config = association_configs[association_config]
61
+ else
62
+ association_configs[association_config] = association_config
63
+ end
64
+ association_config
65
+ end
66
+ end
67
+ end
68
+ end
@@ -12,7 +12,7 @@ module Vorpal
12
12
  end
13
13
 
14
14
  def load_from_db(ids, config)
15
- db_roots = @db_driver.load_by_id(config.db_class, ids)
15
+ db_roots = @db_driver.load_by_unique_key(config.db_class, ids, "id")
16
16
  load_from_db_objects(db_roots, config)
17
17
  end
18
18
 
@@ -24,9 +24,9 @@ module Vorpal
24
24
 
25
25
  until @lookup_instructions.empty?
26
26
  lookup = @lookup_instructions.next_lookup
27
- new_objects = lookup.load_all(@db_driver)
28
- @loaded_objects.add(lookup.config, new_objects)
29
- explore_objects(lookup.config, new_objects)
27
+ newly_loaded_objects = lookup.load_all(@db_driver)
28
+ unexplored_objects = @loaded_objects.add(lookup.config, newly_loaded_objects)
29
+ explore_objects(lookup.config, unexplored_objects)
30
30
  end
31
31
 
32
32
  @loaded_objects
@@ -55,34 +55,34 @@ module Vorpal
55
55
  end
56
56
 
57
57
  def lookup_by_id(db_object, belongs_to_config)
58
- child_config = belongs_to_config.child_config(db_object)
59
- id = belongs_to_config.fk_value(db_object)
60
- return if id.nil? || @loaded_objects.already_loaded?(child_config, id)
61
- @lookup_instructions.lookup_by_id(child_config, id)
58
+ associated_class_config = belongs_to_config.associated_class_config(db_object)
59
+ unique_key_value = belongs_to_config.fk_value(db_object)
60
+ unique_key_name = belongs_to_config.unique_key_name
61
+ return if unique_key_value.nil? || @loaded_objects.already_loaded_by_unique_key?(associated_class_config, unique_key_name, unique_key_value)
62
+ @lookup_instructions.lookup_by_unique_key(associated_class_config, unique_key_name, unique_key_value)
62
63
  end
63
64
 
64
65
  def lookup_by_fk(db_object, has_some_config)
65
- child_config = has_some_config.child_config
66
+ associated_class_config = has_some_config.associated_class_config
66
67
  fk_info = has_some_config.foreign_key_info
67
- fk_value = db_object.id
68
- @lookup_instructions.lookup_by_fk(child_config, fk_info, fk_value)
68
+ fk_value = has_some_config.get_unique_key_value(db_object)
69
+ @lookup_instructions.lookup_by_fk(associated_class_config, fk_info, fk_value)
69
70
  end
70
71
  end
71
72
 
72
73
  # @private
73
74
  class LookupInstructions
74
- include Util::ArrayHash
75
75
  def initialize
76
- @lookup_by_id = {}
77
- @lookup_by_fk = {}
76
+ @lookup_by_id = Util::ArrayHash.new
77
+ @lookup_by_fk = Util::ArrayHash.new
78
78
  end
79
79
 
80
- def lookup_by_id(config, ids)
81
- add_to_hash(@lookup_by_id, config, Array(ids))
80
+ def lookup_by_unique_key(config, column_name, values)
81
+ @lookup_by_id.append([config, column_name], values)
82
82
  end
83
83
 
84
84
  def lookup_by_fk(config, fk_info, fk_value)
85
- add_to_hash(@lookup_by_fk, [config, fk_info], fk_value)
85
+ @lookup_by_fk.append([config, fk_info], fk_value)
86
86
  end
87
87
 
88
88
  def next_lookup
@@ -100,12 +100,14 @@ module Vorpal
100
100
  private
101
101
 
102
102
  def pop_id_lookup
103
- config, ids = pop(@lookup_by_id)
104
- LookupById.new(config, ids)
103
+ key, ids = @lookup_by_id.pop
104
+ config = key.first
105
+ column_name = key.last
106
+ LookupById.new(config, column_name, ids)
105
107
  end
106
108
 
107
109
  def pop_fk_lookup
108
- key, fk_values = pop(@lookup_by_fk)
110
+ key, fk_values = @lookup_by_fk.pop
109
111
  config = key.first
110
112
  fk_info = key.last
111
113
  LookupByFk.new(config, fk_info, fk_values)
@@ -115,14 +117,15 @@ module Vorpal
115
117
  # @private
116
118
  class LookupById
117
119
  attr_reader :config
118
- def initialize(config, ids)
120
+ def initialize(config, column_name, ids)
119
121
  @config = config
122
+ @column_name = column_name
120
123
  @ids = ids
121
124
  end
122
125
 
123
126
  def load_all(db_driver)
124
127
  return [] if @ids.empty?
125
- db_driver.load_by_id(@config.db_class, @ids)
128
+ db_driver.load_by_unique_key(@config.db_class, @ids, @column_name)
126
129
  end
127
130
  end
128
131
 
@@ -9,7 +9,12 @@ module Vorpal
9
9
  end
10
10
 
11
11
  def insert(db_class, db_objects)
12
- if defined? ActiveRecord::Import
12
+ if ActiveRecord::VERSION::MAJOR >= 6
13
+ return if db_objects.empty?
14
+
15
+ update_timestamps_on_create(db_class, db_objects)
16
+ db_class.insert_all!(db_objects.map(&:attributes))
17
+ elsif defined? ActiveRecord::Import
13
18
  db_class.import(db_objects, validate: false)
14
19
  else
15
20
  db_objects.each do |db_object|
@@ -19,8 +24,15 @@ module Vorpal
19
24
  end
20
25
 
21
26
  def update(db_class, db_objects)
22
- db_objects.each do |db_object|
23
- db_object.save!(validate: false)
27
+ if ActiveRecord::VERSION::MAJOR >= 6
28
+ return if db_objects.empty?
29
+
30
+ update_timestamps_on_update(db_class, db_objects)
31
+ db_class.upsert_all(db_objects.map(&:attributes))
32
+ else
33
+ db_objects.each do |db_object|
34
+ db_object.save!(validate: false)
35
+ end
24
36
  end
25
37
  end
26
38
 
@@ -28,12 +40,12 @@ module Vorpal
28
40
  db_class.where(id: ids).delete_all
29
41
  end
30
42
 
31
- # Loads instances of the given class by primary key.
43
+ # Loads instances of the given class by a unique key.
32
44
  #
33
45
  # @param db_class [Class] A subclass of ActiveRecord::Base
34
46
  # @return [[Object]] An array of entities.
35
- def load_by_id(db_class, ids)
36
- db_class.where(id: ids).to_a
47
+ def load_by_unique_key(db_class, ids, column_name)
48
+ db_class.where(column_name => ids).to_a
37
49
  end
38
50
 
39
51
  # Loads instances of the given class whose foreign key has the given value.
@@ -100,6 +112,30 @@ module Vorpal
100
112
 
101
113
  private
102
114
 
115
+ # Adapted from https://github.com/rails/rails/blob/614580270d7789e5275defc3da020ce27b3b2302/activerecord/lib/active_record/timestamp.rb#L99
116
+ def update_timestamps_on_create(db_class, db_objects)
117
+ return unless db_class.record_timestamps
118
+
119
+ current_time = db_class.current_time_from_proper_timezone
120
+ db_objects.each do |db_object|
121
+ db_class.all_timestamp_attributes_in_model.each do |column|
122
+ db_object.write_attribute(column, current_time) unless db_object.read_attribute(column)
123
+ end
124
+ end
125
+ end
126
+
127
+ #Adapted from https://github.com/rails/rails/blob/614580270d7789e5275defc3da020ce27b3b2302/activerecord/lib/active_record/timestamp.rb#L111
128
+ def update_timestamps_on_update(db_class, db_objects)
129
+ return unless db_class.record_timestamps
130
+
131
+ current_time = db_class.current_time_from_proper_timezone
132
+ db_objects.each do |db_object|
133
+ db_class.timestamp_attributes_for_update_in_model.each do |column|
134
+ db_object.write_attribute(column, current_time)
135
+ end
136
+ end
137
+ end
138
+
103
139
  def sequence_name(db_class)
104
140
  @sequence_names[db_class] ||= execute(
105
141
  "SELECT substring(column_default from '''(.*)''') FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1 AND column_name = 'id' LIMIT 1",
@@ -1,4 +1,7 @@
1
- require 'vorpal/configs'
1
+ require 'vorpal/config/class_config'
2
+ require 'vorpal/config/has_many_config'
3
+ require 'vorpal/config/has_one_config'
4
+ require 'vorpal/config/belongs_to_config'
2
5
  require 'vorpal/dsl/defaults_generator'
3
6
 
4
7
  module Vorpal
@@ -16,74 +19,32 @@ module Vorpal
16
19
  @defaults_generator = DefaultsGenerator.new(clazz, db_driver)
17
20
  end
18
21
 
19
- # Maps the given attributes to and from the domain object and the DB. Not needed
20
- # if a serializer and deserializer were provided.
22
+ # @private
21
23
  def attributes(*attributes)
22
24
  @attributes.concat(attributes)
23
25
  end
24
26
 
25
- # Defines a one-to-many association to another type where the foreign key is stored on the child.
26
- #
27
- # In Object-Oriented programming, associations are *directed*. This means that they can only be
28
- # traversed in one direction: from the type that defines the association (the one with the
29
- # getter) to the type that is associated. They end that defines the association is called the
30
- # 'Parent' and the end that is associated is called the 'Child'.
31
- #
32
- # @param name [String] Name of the association getter.
33
- # @param options [Hash]
34
- # @option options [Boolean] :owned (True) True if the child type belongs to the aggregate. Changes to any object belonging to the aggregate will be persisted when the aggregate is persisted.
35
- # @option options [String] :fk (Parent class name converted to snakecase and appended with a '_id') The name of the DB column on the child that contains the foreign key reference to the parent.
36
- # @option options [String] :fk_type The name of the DB column on the child that contains the parent class name. Only needed when there is an association from the child side that is polymorphic.
37
- # @option options [Class] :child_class (name converted to a Class) The child class.
27
+ # @private
38
28
  def has_many(name, options={})
39
- @has_manys << {name: name}.merge(options)
29
+ @has_manys << build_has_many({name: name}.merge(options))
40
30
  end
41
31
 
42
- # Defines a one-to-one association to another type where the foreign key
43
- # is stored on the child.
44
- #
45
- # In Object-Oriented programming, associations are *directed*. This means that they can only be
46
- # traversed in one direction: from the type that defines the association (the one with the
47
- # getter) to the type that is associated. They end that defines the association is called the
48
- # 'Parent' and the end that is associated is called the 'Child'.
49
- #
50
- # @param name [String] Name of the association getter.
51
- # @param options [Hash]
52
- # @option options [Boolean] :owned (True) True if the child type belongs to the aggregate. Changes to any object belonging to the aggregate will be persisted when the aggregate is persisted.
53
- # @option options [String] :fk (Parent class name converted to snakecase and appended with a '_id') The name of the DB column on the child that contains the foreign key reference to the parent.
54
- # @option options [String] :fk_type The name of the DB column on the child that contains the parent class name. Only needed when there is an association from the child side that is polymorphic.
55
- # @option options [Class] :child_class (name converted to a Class) The child class.
32
+ # @private
56
33
  def has_one(name, options={})
57
- @has_ones << {name: name}.merge(options)
34
+ @has_ones << build_has_one({name: name}.merge(options))
58
35
  end
59
36
 
60
- # Defines a one-to-one association with another type where the foreign key
61
- # is stored on the parent.
62
- #
63
- # This association can be polymorphic. I.E. children can be of different types.
64
- #
65
- # In Object-Oriented programming, associations are *directed*. This means that they can only be
66
- # traversed in one direction: from the type that defines the association (the one with the
67
- # getter) to the type that is associated. They end that defines the association is called the
68
- # 'Parent' and the end that is associated is called the 'Child'.
69
- #
70
- # @param name [String] Name of the association getter.
71
- # @param options [Hash]
72
- # @option options [Boolean] :owned (True) True if the child type belongs to the aggregate. Changes to any object belonging to the aggregate will be persisted when the aggregate is persisted.
73
- # @option options [String] :fk (Child class name converted to snakecase and appended with a '_id') The name of the DB column on the parent that contains the foreign key reference to the child.
74
- # @option options [String] :fk_type The name of the DB column on the parent that contains the child class name. Only needed when the association is polymorphic.
75
- # @option options [Class] :child_class (name converted to a Class) The child class.
76
- # @option options [[Class]] :child_classes The list of possible classes that can be children. This is for polymorphic associations. Takes precedence over `:child_class`.
37
+ # @private
77
38
  def belongs_to(name, options={})
78
- @belongs_tos << {name: name}.merge(options)
39
+ @belongs_tos << build_belongs_to({name: name}.merge(options))
79
40
  end
80
41
 
81
42
  # @private
82
43
  def build
83
44
  class_config = build_class_config
84
- class_config.has_manys = build_has_manys
85
- class_config.has_ones = build_has_ones
86
- class_config.belongs_tos = build_belongs_tos
45
+ class_config.has_manys = @has_manys
46
+ class_config.has_ones = @has_ones
47
+ class_config.belongs_tos = @belongs_tos
87
48
 
88
49
  class_config
89
50
  end
@@ -96,46 +57,38 @@ module Vorpal
96
57
  private
97
58
 
98
59
  def build_class_config
99
- Vorpal::ClassConfig.new(
60
+ Vorpal::Config::ClassConfig.new(
100
61
  domain_class: @domain_class,
101
62
  db_class: @class_options[:to] || @defaults_generator.build_db_class(@class_options[:table_name]),
102
63
  serializer: @class_options[:serializer] || @defaults_generator.serializer(attributes_with_id),
103
64
  deserializer: @class_options[:deserializer] || @defaults_generator.deserializer(attributes_with_id),
65
+ primary_key_type: @class_options[:primary_key_type] || @class_options[:id] || :serial,
104
66
  )
105
67
  end
106
68
 
107
- def build_has_manys
108
- @has_manys.map { |options| build_has_many(options) }
109
- end
110
-
111
69
  def build_has_many(options)
112
- options[:child_class] ||= @defaults_generator.child_class(options[:name])
70
+ options[:associated_class] ||= options[:child_class] || @defaults_generator.associated_class(options[:name])
113
71
  options[:fk] ||= @defaults_generator.foreign_key(@domain_class.name)
72
+ options[:unique_key_name] ||= (options[:primary_key] || "id")
114
73
  options[:owned] = options.fetch(:owned, true)
115
- Vorpal::HasManyConfig.new(options)
116
- end
117
-
118
- def build_has_ones
119
- @has_ones.map { |options| build_has_one(options) }
74
+ Vorpal::Config::HasManyConfig.new(options)
120
75
  end
121
76
 
122
77
  def build_has_one(options)
123
- options[:child_class] ||= @defaults_generator.child_class(options[:name])
78
+ options[:associated_class] ||= options[:child_class] || @defaults_generator.associated_class(options[:name])
124
79
  options[:fk] ||= @defaults_generator.foreign_key(@domain_class.name)
80
+ options[:unique_key_name] ||= (options[:primary_key] || "id")
125
81
  options[:owned] = options.fetch(:owned, true)
126
- Vorpal::HasOneConfig.new(options)
127
- end
128
-
129
- def build_belongs_tos
130
- @belongs_tos.map { |options| build_belongs_to(options) }
82
+ Vorpal::Config::HasOneConfig.new(options)
131
83
  end
132
84
 
133
85
  def build_belongs_to(options)
134
- child_class = options[:child_classes] || options[:child_class] || @defaults_generator.child_class(options[:name])
135
- options[:child_classes] = Array(child_class)
86
+ associated_classes = options[:associated_classes] || options[:child_classes] || options[:associated_class] || options[:child_class] || @defaults_generator.associated_class(options[:name])
87
+ options[:associated_classes] = Array(associated_classes)
136
88
  options[:fk] ||= @defaults_generator.foreign_key(options[:name])
89
+ options[:unique_key_name] ||= (options[:primary_key] || "id")
137
90
  options[:owned] = options.fetch(:owned, true)
138
- Vorpal::BelongsToConfig.new(options)
91
+ Vorpal::Config::BelongsToConfig.new(options)
139
92
  end
140
93
  end
141
94
  end