diff --git a/src/masoniteorm/collection/Collection.py b/src/masoniteorm/collection/Collection.py index 53e4f9a4..329ae30d 100644 --- a/src/masoniteorm/collection/Collection.py +++ b/src/masoniteorm/collection/Collection.py @@ -10,6 +10,7 @@ class Collection: def __init__(self, items=None): self._items = items or [] self.__appends__ = [] + self._builder = None def take(self, number: int): """Takes a specific number of results from the items. @@ -578,5 +579,12 @@ def __get_items(cls, items): return items def __call__(self, *args): + model = self.first() + print('callin collectin. has builder?', self._builder) + if not model and self._builder: + return self._builder + + if not model: + return self related = self._items[0].__dict__['related'] return related.apply_query(self._items[0].builder) \ No newline at end of file diff --git a/src/masoniteorm/models/Model.py b/src/masoniteorm/models/Model.py index 64a77438..0bf82962 100644 --- a/src/masoniteorm/models/Model.py +++ b/src/masoniteorm/models/Model.py @@ -1197,7 +1197,7 @@ def has_many(self, related_model_class, foreign_key=None, local_key=None): local_key = f"{related_model_class.get_table_name()}{related_model_class.get_primary_key()}" if not foreign_key: foreign_key = related_model_class.get_primary_key() - return HasMany(related_model_class, foreign_key, local_key)(self) + return HasMany(related_model_class, foreign_key, local_key, self._get_calling_property_name())(self) def _get_calling_property_name(self): """Retrieve the name of the property or method that called this.""" diff --git a/src/masoniteorm/models/relationships/new/HasMany.py b/src/masoniteorm/models/relationships/new/HasMany.py index 7778f905..05c19577 100644 --- a/src/masoniteorm/models/relationships/new/HasMany.py +++ b/src/masoniteorm/models/relationships/new/HasMany.py @@ -1,22 +1,25 @@ from .BaseRelationship import BaseRelationship +from ....collection import Collection class HasMany(BaseRelationship): """Belongs To Relationship Class.""" - def __init__(self, model_class, foreign_key=None, local_key=None): + def __init__(self, model_class, foreign_key=None, local_key=None, method=None): self.model_class = model_class self.foreign_key = foreign_key self.local_key = local_key + self.method = method self.owner = None def apply_query(self, builder, foreign_key_value=None, eager=None): owner = self.owner - foreign_key_value = owner.__attributes__.get(self.foreign_key) + if not foreign_key_value: + foreign_key_value = owner.__attributes__.get(self.local_key) return builder.where(self.local_key, foreign_key_value) def get_related(self, foreign, result, eager=None): - return self.apply_query(self.model_class, getattr(result, self.foreign_key)).first() + return self.apply_query(self.model_class, getattr(result, self.foreign_key)).get() def __call__(self, owner): """Fetch the related record when invoked.""" @@ -27,12 +30,19 @@ def __call__(self, owner): foreign_key_value = owner.__attributes__.get(self.foreign_key) if not foreign_key_value: return self - builder = self.apply_query(related_model.builder) - result = builder.get() + + if self.method and self.method in owner._relationships: + return owner._relationships[self.method] + result = self.apply_query(related_model.builder).get() + result._builder = self.apply_query(self.model_class.builder, foreign_key_value) for item in result: item.__dict__['related'] = self return result def add_relation(self, model_instance, result, relation_key=None): # if result is a collection, do a where - return model_instance.add_relation({relation_key: result or []}) \ No newline at end of file + print("add relation", model_instance, relation_key, result.count()) + result = result or Collection() + result._builder = self.model_class.builder + # print("add relation", model_instance, relation_key, result.count()) + return model_instance.add_relation({relation_key: result}) \ No newline at end of file diff --git a/src/masoniteorm/query/QueryBuilder.py b/src/masoniteorm/query/QueryBuilder.py index c8ebac27..2044edee 100644 --- a/src/masoniteorm/query/QueryBuilder.py +++ b/src/masoniteorm/query/QueryBuilder.py @@ -1900,7 +1900,6 @@ def prepare_result(self, result, collection=False): callback = None print(relation, eagers) related = getattr(self._model, relation) - # Has one from User -> Profile result_set = related.get_related(self, hydrated_model) self._register_relationships_to_model( related, result_set, hydrated_model, relation_key=relation @@ -1917,6 +1916,7 @@ def prepare_result(self, result, collection=False): related = getattr(self._model, eager) result_set = related.get_related(self, hydrated_model) + print('rrr', result_set) self._register_relationships_to_model( related, result_set, hydrated_model, relation_key=eager diff --git a/tests/models/relationships/test_has_many_relationship.py b/tests/models/relationships/test_has_many_relationship.py index 7b9a175a..d2bfd731 100644 --- a/tests/models/relationships/test_has_many_relationship.py +++ b/tests/models/relationships/test_has_many_relationship.py @@ -21,13 +21,13 @@ def test_can_get_owner_value(self): user = User.find(1) self.assertEqual(user.name, "bill") - def test_can_get_has_one_related_value(self): + def test_can_get_has_many_related_value(self): user = User.find(1) for article in user.articles: self.assertEqual(article.title, "masonite") self.assertEqual(user.articles.first().title, "masonite") - def test_can_get_has_one_query_builder(self): + def test_can_get_has_many_query_builder(self): user = User.find(1) self.assertEqual(user.name, "bill") self.assertEqual(user.articles().to_sql(), 'SELECT * FROM "articles" WHERE "articles"."user_id" = \'1\'')