lib/terrestrial/configurations/conventional_association_configuration.rb in terrestrial-0.3.0 vs lib/terrestrial/configurations/conventional_association_configuration.rb in terrestrial-0.5.0
- old
+ new
@@ -8,26 +8,26 @@
require "terrestrial/collection_mutability_proxy"
require "terrestrial/lazy_collection"
require "terrestrial/lazy_object_proxy"
class ConventionalAssociationConfiguration
- def initialize(mapping_name, mappings, datastore)
- @local_mapping_name = mapping_name
- @mappings = mappings
- @local_mapping = mappings.fetch(local_mapping_name)
+ def initialize(inflector, datastore, mapping_name, mappings)
+ @inflector = inflector
@datastore = datastore
+ @target_mapping = mappings.fetch(mapping_name)
+ @mappings = mappings
end
- attr_reader :local_mapping_name, :local_mapping, :mappings, :datastore
- private :local_mapping_name, :local_mapping, :mappings, :datastore
+ attr_reader :inflector, :datastore, :target_mapping, :mappings
+ private :inflector, :datastore, :target_mapping, :mappings
DEFAULT = Module.new
def has_many(association_name, key: DEFAULT, foreign_key: DEFAULT, mapping_name: DEFAULT, order_fields: DEFAULT, order_direction: DEFAULT)
defaults = {
mapping_name: association_name,
- foreign_key: [INFLECTOR.singularize(local_mapping_name), "_id"].join.to_sym,
+ foreign_key: [singular_name, "_id"].join.to_sym,
key: :id,
order_fields: [],
order_direction: "ASC",
}
@@ -43,21 +43,18 @@
config = defaults.merge(specified)
associated_mapping_name = config.fetch(:mapping_name)
associated_mapping = mappings.fetch(associated_mapping_name)
- local_mapping.add_association(
- association_name,
- has_many_mapper(**config)
- )
+ has_many_mapper(**config)
end
def belongs_to(association_name, key: DEFAULT, foreign_key: DEFAULT, mapping_name: DEFAULT)
defaults = {
key: :id,
foreign_key: [association_name, "_id"].join.to_sym,
- mapping_name: INFLECTOR.pluralize(association_name).to_sym,
+ mapping_name: pluralize(association_name).to_sym,
}
specified = {
mapping_name: mapping_name,
foreign_key: foreign_key,
@@ -69,23 +66,21 @@
config = defaults.merge(specified)
associated_mapping_name = config.fetch(:mapping_name)
associated_mapping = mappings.fetch(associated_mapping_name)
- local_mapping.add_association(
- association_name,
- belongs_to_mapper(**config)
- )
+ belongs_to_mapper(**config)
end
- def has_many_through(association_name, key: DEFAULT, foreign_key: DEFAULT, mapping_name: DEFAULT, through_mapping_name: DEFAULT, association_key: DEFAULT, association_foreign_key: DEFAULT, order_fields: DEFAULT, order_direction: DEFAULT)
+ def has_many_through(association_name, key: DEFAULT, foreign_key: DEFAULT, mapping_name: DEFAULT, through_table_name: DEFAULT, association_key: DEFAULT, association_foreign_key: DEFAULT, order_fields: DEFAULT, order_direction: DEFAULT)
+ # TODO: join_dataset as mutually exclusive option with join_table_name
defaults = {
mapping_name: association_name,
key: :id,
association_key: :id,
- foreign_key: [INFLECTOR.singularize(local_mapping_name), "_id"].join.to_sym,
- association_foreign_key: [INFLECTOR.singularize(association_name), "_id"].join.to_sym,
+ foreign_key: [singular_name, "_id"].join.to_sym,
+ association_foreign_key: [singularize(association_name), "_id"].join.to_sym,
order_fields: [],
order_direction: "ASC",
}
specified = {
@@ -99,30 +94,34 @@
}.reject { |_k,v|
v == DEFAULT
}
config = defaults.merge(specified)
+
associated_mapping = mappings.fetch(config.fetch(:mapping_name))
+ default_through_table_name = [associated_mapping.name, target_mapping.name].sort.join("_to_").to_sym
- if through_mapping_name == DEFAULT
- through_mapping_name = [
- associated_mapping.name,
- local_mapping.name,
- ].sort.join("_to_").to_sym
+ if through_table_name == DEFAULT
+ through_table_name = default_through_table_name
end
- join_table_name = mappings.fetch(through_mapping_name).namespace
- config = config
- .merge(
- through_mapping_name: through_mapping_name,
- through_dataset: datastore[join_table_name.to_sym],
- )
+ join_mapping = create_virtual_mapping(
+ default_mapping_name: default_through_table_name,
+ namespace: through_table_name,
+ primary_key: [config[:foreign_key], config[:association_foreign_key]],
+ )
- local_mapping.add_association(
- association_name,
- has_many_through_mapper(**config)
+ mappings[join_mapping.name] = join_mapping
+
+ join_dataset = datastore[through_table_name.to_sym]
+
+ config = config.merge(
+ join_mapping_name: join_mapping.name,
+ join_dataset: join_dataset,
)
+
+ has_many_through_mapper(**config)
end
private
def has_many_mapper(mapping_name:, key:, foreign_key:, order_fields:, order_direction:)
@@ -142,23 +141,42 @@
key: key,
proxy_factory: single_object_proxy_factory,
)
end
- def has_many_through_mapper(mapping_name:, key:, foreign_key:, association_key:, association_foreign_key:, through_mapping_name:, through_dataset:, order_fields:, order_direction:)
+ def has_many_through_mapper(mapping_name:, key:, foreign_key:, association_key:, association_foreign_key:, join_mapping_name:, join_dataset:, order_fields:, order_direction:)
ManyToManyAssociation.new(
mapping_name: mapping_name,
- join_mapping_name: through_mapping_name,
+ join_mapping_name: join_mapping_name,
+ join_dataset: join_dataset, # TODO: this dataset is not used
key: key,
foreign_key: foreign_key,
association_key: association_key,
association_foreign_key: association_foreign_key,
proxy_factory: collection_proxy_factory,
order: query_order(order_fields, order_direction),
)
end
+ def create_virtual_mapping(default_mapping_name:, namespace:, primary_key:)
+ mapping_name = "__generated_virtual_mapping_#{default_mapping_name}"
+
+ RelationMapping.new(
+ name: mapping_name,
+ namespace: namespace,
+ primary_key: primary_key,
+ factory: ->(*_) { },
+ serializer: :to_h.to_proc,
+ fields: [],
+ associations: [],
+ subsets: [],
+ database_owned_fields: [],
+ database_default_fields: [],
+ observers: [],
+ )
+ end
+
def single_object_proxy_factory
->(query:, loader:, preloaded_data:) {
LazyObjectProxy.new(
->{ loader.call(query.first) },
preloaded_data,
@@ -178,9 +196,21 @@
}
end
def query_order(fields, direction)
QueryOrder.new(fields: fields, direction: direction)
+ end
+
+ def singular_name
+ inflector.singularize(target_mapping.name)
+ end
+
+ def singularize(string)
+ inflector.singularize(string)
+ end
+
+ def pluralize(string)
+ inflector.pluralize(string)
end
end
end
end