added observer to repository and updated tests
This commit is contained in:
parent
6307850721
commit
5e2d2ddde5
|
|
@ -36,6 +36,9 @@ public:
|
||||||
|
|
||||||
void update_name(const std::string& name) const;
|
void update_name(const std::string& name) const;
|
||||||
|
|
||||||
|
virtual void on_attach() const = 0;
|
||||||
|
virtual void on_detach() const = 0;
|
||||||
|
|
||||||
endpoint_iterator register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint);
|
endpoint_iterator register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint);
|
||||||
void unregister_relation_endpoint(const std::type_index &type);
|
void unregister_relation_endpoint(const std::type_index &type);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto node = repository_node::make_node<Type>(repo_.repo(), "");
|
const auto node = repository_node::make_node<Type>(repo_.repo(), "", []{ return std::make_unique<Type>(); });
|
||||||
if (auto result = repo_.attach_node(node)) {
|
if (auto result = repo_.attach_node(node)) {
|
||||||
foreign_node_completer<Type>::complete(result.value());
|
foreign_node_completer<Type>::complete(result.value());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,28 @@
|
||||||
#define OBJECT_INFO_HPP
|
#define OBJECT_INFO_HPP
|
||||||
|
|
||||||
#include "matador/object/basic_object_info.hpp"
|
#include "matador/object/basic_object_info.hpp"
|
||||||
|
#include "matador/object/observer.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace matador::object {
|
namespace matador::object {
|
||||||
class repository_node;
|
class repository_node;
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class observer_ptr {
|
||||||
|
public:
|
||||||
|
explicit observer_ptr(std::unique_ptr<observer<Type>> &&observer)
|
||||||
|
: observer(std::move(observer)) {}
|
||||||
|
|
||||||
|
operator bool() const { return observer != nullptr; }
|
||||||
|
|
||||||
|
observer<Type> *get() const { return observer.get(); }
|
||||||
|
observer<Type> &operator*() const { return *observer; }
|
||||||
|
observer<Type> *operator->() const { return observer.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<observer<Type>> observer;
|
||||||
|
};
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
class object_info final : public basic_object_info {
|
class object_info final : public basic_object_info {
|
||||||
public:
|
public:
|
||||||
|
|
@ -27,9 +43,25 @@ public:
|
||||||
const Type &prototype() const { return prototype_; }
|
const Type &prototype() const { return prototype_; }
|
||||||
std::unique_ptr<Type> create() const { return creator_(); }
|
std::unique_ptr<Type> create() const { return creator_(); }
|
||||||
|
|
||||||
|
void on_attach() const override {
|
||||||
|
for (auto &observer : observers_) {
|
||||||
|
observer->on_attach(*node_, prototype_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_detach() const override {
|
||||||
|
for (auto &observer : observers_) {
|
||||||
|
observer->on_detach(*node_, prototype_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_observer(observer_ptr<Type> observer) {
|
||||||
|
observers_.push_back(std::move(observer));
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
Type prototype_;
|
Type prototype_;
|
||||||
create_func creator_{[]{ return std::make_unique<Type>(); }};
|
create_func creator_{[]{ return std::make_unique<Type>(); }};
|
||||||
|
std::vector<observer_ptr<Type>> observers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
#ifndef MATADOR_OBSERVER_HPP
|
||||||
|
#define MATADOR_OBSERVER_HPP
|
||||||
|
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
|
namespace matador::object {
|
||||||
|
class repository_node;
|
||||||
|
|
||||||
|
class abstract_observer {
|
||||||
|
public:
|
||||||
|
virtual ~abstract_observer() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Constructs a basic_object_store_observer for the
|
||||||
|
* give std::type_index.
|
||||||
|
*
|
||||||
|
* @param ti type index of the observer
|
||||||
|
*/
|
||||||
|
explicit abstract_observer(const std::type_index &ti);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Return the type index of the observer.
|
||||||
|
*
|
||||||
|
* @return The type index of the observer.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] const std::type_index& index() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::type_index type_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class observer
|
||||||
|
* @tparam Type Type of the observer
|
||||||
|
* @brief Base class for typed observer classes
|
||||||
|
*
|
||||||
|
* When interested in observe
|
||||||
|
* - attach (prototype_node)
|
||||||
|
* - detach (prototype_node)
|
||||||
|
* - insert (an object)
|
||||||
|
* - update (an object)
|
||||||
|
* - delete (an object)
|
||||||
|
* actions an observer class instance must be
|
||||||
|
* registered within the repository.
|
||||||
|
* Use this class as a base class for all observer classes.
|
||||||
|
*/
|
||||||
|
template < class Type >
|
||||||
|
class observer : public abstract_observer {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
|
observer() : abstract_observer(std::type_index(typeid(Type))) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on repository_node attachment
|
||||||
|
*
|
||||||
|
* When a prototype node is attached to the repository,
|
||||||
|
* this is called after the attaching succeeded.
|
||||||
|
*
|
||||||
|
* @param node The attached repository_node
|
||||||
|
* @param prototype The prototype object of the attached node
|
||||||
|
*/
|
||||||
|
virtual void on_attach(repository_node &node, const Type &prototype) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on repository_node detached
|
||||||
|
*
|
||||||
|
* When a prototype node is detached from the repository,
|
||||||
|
* this is called before the detaching succeeded.
|
||||||
|
*
|
||||||
|
* @param node The to be detached repository_node
|
||||||
|
* @param prototype The prototype object of the detached node
|
||||||
|
*/
|
||||||
|
virtual void on_detach(repository_node &node, const Type &prototype) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on object insertion.
|
||||||
|
*
|
||||||
|
* Called when an object is inserted
|
||||||
|
* into the repository.
|
||||||
|
*
|
||||||
|
* @param obj The proxy of the inserted object.
|
||||||
|
*/
|
||||||
|
virtual void on_insert(Type &obj) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on object update.
|
||||||
|
*
|
||||||
|
* Called when an object is updated
|
||||||
|
* in the repository.
|
||||||
|
*
|
||||||
|
* @param obj The proxy of the updated object.
|
||||||
|
*/
|
||||||
|
virtual void on_update(Type &obj) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on object deletion.
|
||||||
|
*
|
||||||
|
* Called when an object is deleted
|
||||||
|
* from the repository.
|
||||||
|
*
|
||||||
|
* @param obj The proxy of the deleted object.
|
||||||
|
*/
|
||||||
|
virtual void on_delete(Type &obj) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template < class Type >
|
||||||
|
class null_observer : public observer<Type> {
|
||||||
|
public:
|
||||||
|
template < class OtherType >
|
||||||
|
explicit null_observer(const null_observer<OtherType> *) {}
|
||||||
|
void on_attach(repository_node &, Type &) override {}
|
||||||
|
void on_detach(repository_node &, Type &) override {}
|
||||||
|
void on_insert(Type &) override {}
|
||||||
|
void on_update(Type &) override {}
|
||||||
|
void on_delete(Type &) override {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //MATADOR_OBSERVER_HPP
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "matador/object/error_code.hpp"
|
#include "matador/object/error_code.hpp"
|
||||||
#include "matador/object/foreign_node_completer.hpp"
|
#include "matador/object/foreign_node_completer.hpp"
|
||||||
#include "matador/object/object_info.hpp"
|
#include "matador/object/object_info.hpp"
|
||||||
|
#include "matador/object/observer.hpp"
|
||||||
#include "matador/object/relation_completer.hpp"
|
#include "matador/object/relation_completer.hpp"
|
||||||
#include "matador/object/repository_node.hpp"
|
#include "matador/object/repository_node.hpp"
|
||||||
#include "matador/object/repository_node_iterator.hpp"
|
#include "matador/object/repository_node_iterator.hpp"
|
||||||
|
|
@ -37,14 +38,37 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit repository(std::string name = "");
|
explicit repository(std::string name = "");
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type, typename... Observers>
|
||||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent = "") {
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||||
|
return attach_type<Type, Observers...>(name, std::string{}, std::forward<Observers>(observers)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type, typename SuperType, typename... Observers>
|
||||||
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||||
|
const auto ti = std::type_index(typeid(SuperType));
|
||||||
|
auto result = find_node(ti);
|
||||||
|
if (!result) {
|
||||||
|
return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + std::string(ti.name()) + "' not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return attach_type<Type, Observers...>(name, (*result)->name(), std::forward<Observers>(observers)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type, typename... Observers>
|
||||||
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent, Observers&&... observers) {
|
||||||
|
return attach_type<Type, Observers...>(name, parent, std::forward<Observers>(observers)...);
|
||||||
|
}
|
||||||
|
template<typename Type, typename... Observers>
|
||||||
|
[[nodiscard]] utils::result<void, utils::error> attach_type(const std::string &name, const std::string &parent, Observers&&... observers) {
|
||||||
if (const auto it = nodes_by_type_.find(typeid(Type)); it == nodes_by_type_.end() ) {
|
if (const auto it = nodes_by_type_.find(typeid(Type)); it == nodes_by_type_.end() ) {
|
||||||
// if the type was not found
|
// if the type was not found
|
||||||
auto node = repository_node::make_node<Type>(*this, name);
|
auto node = repository_node::make_node<Type>(*this, name, []{ return std::make_unique<Type>(); }, std::forward<Observers>(observers)...);
|
||||||
if (auto result = attach_node(node, parent); !result) {
|
if (auto result = attach_node(node, parent); !result) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->on_attach();
|
||||||
|
|
||||||
foreign_node_completer<Type>::complete(node);
|
foreign_node_completer<Type>::complete(node);
|
||||||
relation_completer<Type>::complete(node);
|
relation_completer<Type>::complete(node);
|
||||||
} else if (!has_node(name)) {
|
} else if (!has_node(name)) {
|
||||||
|
|
@ -56,25 +80,12 @@ public:
|
||||||
relation_completer<Type>::complete(it->second);
|
relation_completer<Type>::complete(it->second);
|
||||||
log_.info("attach: update node name to '%s' (type: %s)", it->second->name().c_str(), it->second->type_index().name());
|
log_.info("attach: update node name to '%s' (type: %s)", it->second->name().c_str(), it->second->type_index().name());
|
||||||
} else {
|
} else {
|
||||||
// remove_node( )
|
|
||||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + name + "' already exists"));
|
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + name + "' already exists"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok<void>();
|
return utils::ok<void>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type, typename SuperType>
|
|
||||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name) {
|
|
||||||
const auto ti = std::type_index(typeid(SuperType));
|
|
||||||
auto result = find_node(ti);
|
|
||||||
if (!result) {
|
|
||||||
return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + std::string(ti.name()) + "' not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return attach<Type>(name, (*result)->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches a given node from the schema. If the
|
* Detaches a given node from the schema. If the
|
||||||
* node is a parent of other nodes, these nodes are
|
* node is a parent of other nodes, these nodes are
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ public:
|
||||||
template< typename Type>
|
template< typename Type>
|
||||||
using creator_func = std::function<std::unique_ptr<Type>()>;
|
using creator_func = std::function<std::unique_ptr<Type>()>;
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type, typename... Observers >
|
||||||
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name, creator_func<Type> creator = []{ return std::make_unique<Type>(); }) {
|
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name, creator_func<Type> creator, Observers&&... observers) {
|
||||||
const std::type_index ti(typeid(Type));
|
const std::type_index ti(typeid(Type));
|
||||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, ti));
|
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, ti));
|
||||||
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
std::move(obj),
|
std::move(obj),
|
||||||
std::forward<creator_func<Type>>(creator)
|
std::forward<creator_func<Type>>(creator)
|
||||||
);
|
);
|
||||||
|
(info->register_observer(observer_ptr<Type>(std::unique_ptr<Observers>(new Observers(std::forward<Observers>(observers))))), ...);
|
||||||
node->info_ = std::move(info);
|
node->info_ = std::move(info);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
@ -63,6 +64,9 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] bool has_children() const;
|
[[nodiscard]] bool has_children() const;
|
||||||
|
|
||||||
|
void on_attach() const;
|
||||||
|
void on_detach() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit repository_node(repository& repo);
|
explicit repository_node(repository& repo);
|
||||||
repository_node(repository& repo, const std::type_index& ti);
|
repository_node(repository& repo, const std::type_index& ti);
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,14 @@ public:
|
||||||
explicit schema(sql::connection_pool &pool);
|
explicit schema(sql::connection_pool &pool);
|
||||||
schema(sql::connection_pool &pool, const std::string &name);
|
schema(sql::connection_pool &pool, const std::string &name);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type, template <typename> class ObserverType>
|
||||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent = "") {
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent = "", std::initializer_list<ObserverType<Type>*> observer = {}) {
|
||||||
return repo_.attach<Type>(name, parent);
|
return repo_.attach<Type>(name, parent, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type, typename SuperType>
|
template<typename Type, typename SuperType, template <typename> class ObserverType>
|
||||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name) {
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, std::initializer_list<ObserverType<Type>*> observer = {}) {
|
||||||
return repo_.attach<Type, SuperType>(name);
|
return repo_.attach<Type, SuperType>(name, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] utils::result<void, utils::error> create() const;
|
[[nodiscard]] utils::result<void, utils::error> create() const;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/object/object_info.hpp
|
../../include/matador/object/object_info.hpp
|
||||||
../../include/matador/object/object_proxy.hpp
|
../../include/matador/object/object_proxy.hpp
|
||||||
../../include/matador/object/object_ptr.hpp
|
../../include/matador/object/object_ptr.hpp
|
||||||
|
../../include/matador/object/observer.hpp
|
||||||
../../include/matador/object/primary_key_resolver.hpp
|
../../include/matador/object/primary_key_resolver.hpp
|
||||||
../../include/matador/object/relation_completer.hpp
|
../../include/matador/object/relation_completer.hpp
|
||||||
../../include/matador/object/relation_endpoint.hpp
|
../../include/matador/object/relation_endpoint.hpp
|
||||||
|
|
@ -83,6 +84,7 @@ add_library(matador-core STATIC
|
||||||
object/internal/shadow_repository.cpp
|
object/internal/shadow_repository.cpp
|
||||||
object/object.cpp
|
object/object.cpp
|
||||||
object/object_generator.cpp
|
object/object_generator.cpp
|
||||||
|
object/observer.cpp
|
||||||
object/relation_endpoint.cpp
|
object/relation_endpoint.cpp
|
||||||
object/repository.cpp
|
object/repository.cpp
|
||||||
object/repository_node.cpp
|
object/repository_node.cpp
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "matador/object/observer.hpp"
|
||||||
|
|
||||||
|
namespace matador::object {
|
||||||
|
abstract_observer::abstract_observer(const std::type_index& ti)
|
||||||
|
: type_index_(ti) {}
|
||||||
|
|
||||||
|
const std::type_index& abstract_observer::index() const {
|
||||||
|
return type_index_;
|
||||||
|
}
|
||||||
|
} // namespace matador::object
|
||||||
|
|
@ -55,7 +55,11 @@ const repository& repository_node::schema() const {
|
||||||
bool repository_node::has_children() const {
|
bool repository_node::has_children() const {
|
||||||
return first_child_->next_sibling_ != last_child_;
|
return first_child_->next_sibling_ != last_child_;
|
||||||
}
|
}
|
||||||
|
void repository_node::on_attach() const {
|
||||||
|
info_->on_attach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void repository_node::on_detach() const {}
|
||||||
repository_node::node_ptr repository_node::next() const {
|
repository_node::node_ptr repository_node::next() const {
|
||||||
// if we have a child, child is the next iterator to return
|
// if we have a child, child is the next iterator to return
|
||||||
// (if we don't iterate over the siblings)
|
// (if we don't iterate over the siblings)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "../../models/department.hpp"
|
#include "../../models/department.hpp"
|
||||||
#include "../../models/recipe.hpp"
|
#include "../../models/recipe.hpp"
|
||||||
|
#include "../../models/person.hpp"
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
};
|
};
|
||||||
|
|
@ -105,14 +106,14 @@ TEST_CASE("Test one to many", "[relation][one-to-many]") {
|
||||||
REQUIRE(repo.contains("departments"));
|
REQUIRE(repo.contains("departments"));
|
||||||
REQUIRE(repo.contains("employees"));
|
REQUIRE(repo.contains("employees"));
|
||||||
|
|
||||||
auto info = repo.basic_info("departments")->get();
|
auto result = repo.basic_info("departments");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
std::cout << *info.object();
|
std::cout << *result->get().object();
|
||||||
info = repo.basic_info("employees")->get();
|
result = repo.basic_info("employees");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
std::cout << *info.object();
|
std::cout << *result->get().object();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") {
|
TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") {
|
||||||
|
|
@ -127,14 +128,15 @@ TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") {
|
||||||
REQUIRE(repo.contains("departments"));
|
REQUIRE(repo.contains("departments"));
|
||||||
REQUIRE(repo.contains("employees"));
|
REQUIRE(repo.contains("employees"));
|
||||||
|
|
||||||
auto info = repo.basic_info("departments")->get();
|
auto result = repo.basic_info("departments");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(result.is_ok());
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
std::cout << *info.object();
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
info = repo.basic_info("employees")->get();
|
std::cout << *result->get().object();
|
||||||
REQUIRE(!info.endpoints_empty());
|
result = repo.basic_info("employees");
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
std::cout << *info.object();
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
|
std::cout << *result->get().object();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
||||||
|
|
@ -142,9 +144,9 @@ TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
||||||
|
|
||||||
REQUIRE(repo.empty());
|
REQUIRE(repo.empty());
|
||||||
|
|
||||||
auto result = repo.attach<test::recipe>("recipes")
|
auto res = repo.attach<test::recipe>("recipes")
|
||||||
.and_then([&repo] { return repo.attach<test::ingredient>("ingredients"); });
|
.and_then([&repo] { return repo.attach<test::ingredient>("ingredients"); });
|
||||||
REQUIRE(result);
|
REQUIRE(res);
|
||||||
|
|
||||||
REQUIRE(repo.size() == 3);
|
REQUIRE(repo.size() == 3);
|
||||||
REQUIRE(repo.contains("ingredients"));
|
REQUIRE(repo.contains("ingredients"));
|
||||||
|
|
@ -156,16 +158,44 @@ TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
||||||
std::cout << *repo.basic_info("recipe_ingredients")->get().object();
|
std::cout << *repo.basic_info("recipe_ingredients")->get().object();
|
||||||
|
|
||||||
|
|
||||||
auto info = repo.basic_info("ingredients")->get();
|
auto result = repo.basic_info("ingredients");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
std::cout << *info.object();
|
std::cout << *result->get().object();
|
||||||
info = repo.basic_info("recipes")->get();
|
result = repo.basic_info("recipes");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
REQUIRE(info.endpoints_size() == 1);
|
REQUIRE(result->get().endpoints_size() == 1);
|
||||||
std::cout << *info.object();
|
std::cout << *result->get().object();
|
||||||
info = repo.basic_info("recipe_ingredients")->get();
|
result = repo.basic_info("recipe_ingredients");
|
||||||
REQUIRE(!info.endpoints_empty());
|
REQUIRE(!result->get().endpoints_empty());
|
||||||
REQUIRE(info.endpoints_size() == 2);
|
REQUIRE(result->get().endpoints_size() == 2);
|
||||||
std::cout << *info.object();
|
std::cout << *result->get().object();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class test_observer : public matador::object::observer<Type> {
|
||||||
|
public:
|
||||||
|
void on_attach(object::repository_node& node, const Type& prototype) override {
|
||||||
|
int i = 0;
|
||||||
|
}
|
||||||
|
void on_detach(object::repository_node& node, const Type& prototype) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
void on_insert(Type& obj) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
void on_update(Type& obj) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
void on_delete(Type& obj) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TEST_CASE("Test repository observer", "[repository][observer]") {
|
||||||
|
object::repository repo;
|
||||||
|
|
||||||
|
REQUIRE(repo.empty());
|
||||||
|
|
||||||
|
const auto result = repo.attach<test::person>("person", test_observer<test::person>());
|
||||||
|
REQUIRE(result.is_ok());
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue