diff --git a/docs/tinyorm-relationships.md b/docs/tinyorm-relationships.md index 7157e5931..490a0f578 100644 --- a/docs/tinyorm-relationships.md +++ b/docs/tinyorm-relationships.md @@ -661,7 +661,7 @@ When defining the `RoleUser` model, you should extend the `Orm::Tiny::Relations: #endif // ROLEUSER_H -You have to pass a custom pivot type to the `AllRelations` template parameter pack on `BaseModel` so that the `BaseModel` knows how to generate a `std::variant`, which holds all the relations and also add a new mapping from the relation name to the custom pivot model type-id, this is described in more detail in the [Common Rules](#common-rules): +You have to pass a custom pivot type to the `AllRelations` template parameter pack on `BaseModel` so that the `BaseModel` knows how to generate a `std::variant`, which holds all the relations and also you have to add a new mapping from the relation name to the custom pivot model type-id, this is described in more detail in the [Common Rules](#common-rules): #ifndef ROLE_H #define ROLE_H diff --git a/include/orm/tiny/relations/relation.hpp b/include/orm/tiny/relations/relation.hpp index 13e49f1bf..d6ffd1157 100644 --- a/include/orm/tiny/relations/relation.hpp +++ b/include/orm/tiny/relations/relation.hpp @@ -471,10 +471,10 @@ namespace Relations /*! The textual representation of the Relation type. */ virtual QString relationTypeName() const = 0; - /* During eager load, we secure m_parent not to become a dangling reference in + /* During eager load, we secure m_parent to not become a dangling reference in TinyBuilder::eagerLoadRelation() by help of the dummyModel local variable. - During lazy loads, m_parent refers to the model that initiated the lazy - load. */ + It has to be the reference, because eg BelongsTo::associate() directly + modifies attributes of m_parent. */ /*! The parent model instance. */ Model &m_parent; /*! The related model instance. */ diff --git a/include/orm/tiny/tinybuilder.hpp b/include/orm/tiny/tinybuilder.hpp index 41bf7ef9a..4a0ff614b 100644 --- a/include/orm/tiny/tinybuilder.hpp +++ b/include/orm/tiny/tinybuilder.hpp @@ -1190,9 +1190,10 @@ namespace Relations const WithItem &relationItem) { /*! Helping model for eager loads, because Relation::m_parent has to be - reference, this dummy model prevents dangling reference, have to secure + reference, this dummy model prevents dangling reference, we have to secure that the model passed to the relation method called inside getRelation() - will live long enough not to become a dangling reference. + will live long enough, to not become a dangling reference. + Have to exists, until the 'relation->match()' is processed in this method. Look at Relation::m_parent for additional info. */ auto dummyModel = getModel().newInstance(); diff --git a/tests/auto/functional/orm/tiny/models/models/role.hpp b/tests/auto/functional/orm/tiny/models/models/role.hpp new file mode 100644 index 000000000..ac0e9ee85 --- /dev/null +++ b/tests/auto/functional/orm/tiny/models/models/role.hpp @@ -0,0 +1,45 @@ +#ifndef ROLE_H +#define ROLE_H + +#include + +class User; // Forward declaration to avoid cyclic dependency + +#include "models/roleuser.hpp" + +using Orm::Tiny::BaseModel; +using Orm::Tiny::Relations::Pivot; +using Orm::Tiny::Relations::Relation; + +class Role final : public BaseModel +//class Role final : public BaseModel +{ + friend BaseModel; + using BaseModel::BaseModel; + +public: + /*! The users that belong to the role. */ + std::unique_ptr> + users() + { + return belongsToMany(); + } + +private: + /*! The visitor to obtain a type for Related template parameter. */ + void relationVisitor(const QString &relation) + { + if (relation == "users") + relationVisited(); + else if (relation == "pivot") // Pivot + relationVisited(); +// relationVisited(); + } + + /*! Map of relation names to methods. */ + QHash u_relations { + {"users", &Role::users}, + }; +}; + +#endif // ROLE_H diff --git a/tests/auto/functional/orm/tiny/models/models/roleuser.hpp b/tests/auto/functional/orm/tiny/models/models/roleuser.hpp new file mode 100644 index 000000000..208a2b212 --- /dev/null +++ b/tests/auto/functional/orm/tiny/models/models/roleuser.hpp @@ -0,0 +1,16 @@ +#ifndef ROLEUSER_H +#define ROLEUSER_H + +#include "orm/tiny/relations/basepivot.hpp" + +using Orm::Tiny::Relations::BasePivot; + +class RoleUser final : public BasePivot +{ + friend BaseModel; + friend BasePivot; + + using BasePivot::BasePivot; +}; + +#endif // ROLEUSER_H diff --git a/tests/auto/functional/orm/tiny/models/models/tag.hpp b/tests/auto/functional/orm/tiny/models/models/tag.hpp index 5b5f3df6a..b507dd5a5 100644 --- a/tests/auto/functional/orm/tiny/models/models/tag.hpp +++ b/tests/auto/functional/orm/tiny/models/models/tag.hpp @@ -28,6 +28,7 @@ public: auto relation = belongsToMany(); dynamic_cast &>(*relation) // .as("tagged") + .as("subscription") .withPivot("active") .withTimestamps(); diff --git a/tests/auto/functional/orm/tiny/models/models/user.hpp b/tests/auto/functional/orm/tiny/models/models/user.hpp new file mode 100644 index 000000000..8e8a28098 --- /dev/null +++ b/tests/auto/functional/orm/tiny/models/models/user.hpp @@ -0,0 +1,52 @@ +#ifndef USER_H +#define USER_H + +#include + +#include "models/role.hpp" + +using Orm::Tiny::BaseModel; +using Orm::Tiny::Relations::Pivot; +using Orm::Tiny::Relations::Relation; + +class User final : public BaseModel +{ + friend BaseModel; + using BaseModel::BaseModel; + +public: + /*! The roles that belong to the user. */ + std::unique_ptr> + roles() + { + using Orm::Tiny::Relations::BelongsToMany; + + // Ownership of a unique_ptr() + auto relation = belongsToMany(); + dynamic_cast &>(*relation) +// .as("subscription") + .withPivot("active"); +// .withTimestamps(); + + return relation; +// return belongsToMany(); +// return belongsToMany(); + } + +private: + /*! The visitor to obtain a type for Related template parameter. */ + void relationVisitor(const QString &relation) + { + if (relation == "roles") + relationVisited(); + else if (relation == "pivot") // Pivot + relationVisited(); + } + + /*! Map of relation names to methods. */ + QHash u_relations { + {"roles", &User::roles}, + }; +}; + +#endif // USER_H