add 'private' interface to category class
This commit is contained in:
parent
bd6a6aefe3
commit
f689cbd60a
@ -7,7 +7,7 @@
|
||||
namespace eedb::pg {
|
||||
class Connection;
|
||||
|
||||
class CategoriesImpl : public Categories {
|
||||
class CategoriesImpl : public CategoriesChildren {
|
||||
// Categories interface
|
||||
public:
|
||||
CategoriesImpl(std::unique_ptr< std::vector< std::unique_ptr< eedb::Category > > > data);
|
||||
|
||||
@ -9,9 +9,24 @@ class User;
|
||||
}
|
||||
|
||||
namespace eedb::pg {
|
||||
namespace impl {
|
||||
/**
|
||||
* @brief The PgCategory class
|
||||
*
|
||||
* 'private part' of categories class
|
||||
*/
|
||||
class PgCategory : public ::eedb::Category {
|
||||
/**
|
||||
* @brief id
|
||||
* @return id of object in database
|
||||
*/
|
||||
virtual int64_t id() const = 0;
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
class Connection;
|
||||
|
||||
class CategoryImpl : public Category {
|
||||
class CategoryImpl : public impl::PgCategory {
|
||||
private:
|
||||
struct CategoryImplPrivate;
|
||||
spimpl::impl_ptr< CategoryImplPrivate > _priv;
|
||||
@ -22,13 +37,14 @@ class CategoryImpl : public Category {
|
||||
|
||||
string_view displayName() const override;
|
||||
|
||||
string_view path() const override;
|
||||
|
||||
Category * parent() const override;
|
||||
|
||||
std::unique_ptr< Categories > children() const override;
|
||||
std::unique_ptr< CategoriesChildren > children() const override;
|
||||
|
||||
std::unique_ptr< Category > create(std::string name, std::string description) const override;
|
||||
|
||||
public:
|
||||
int64_t id() const override;
|
||||
};
|
||||
|
||||
} // namespace eedb
|
||||
} // namespace eedb::pg
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <eedb/mock/db/CategoryMock.hpp>
|
||||
#include <eedb/pg/Category.hpp>
|
||||
|
||||
#include <eedb/pg/connection.hpp>
|
||||
#include <eedb/pg/model/all.hpp>
|
||||
@ -12,7 +12,8 @@
|
||||
|
||||
namespace eedb::pg {
|
||||
|
||||
class CategoryMock : public ::eedb::CategoryMock {
|
||||
class CategoryMock : public impl::PgCategory {
|
||||
public:
|
||||
auto _createChild(int64_t parentId, std::string name) {
|
||||
return _db(sqlpp::postgresql::insert_into(t_category) //
|
||||
.set(t_category.name = name, t_category.parent_id = parentId)
|
||||
@ -22,39 +23,46 @@ class CategoryMock : public ::eedb::CategoryMock {
|
||||
}
|
||||
|
||||
void _root_guard() {
|
||||
if(!_root_id)
|
||||
if(!_id)
|
||||
_initRoot();
|
||||
}
|
||||
|
||||
public:
|
||||
CategoryMock(Connection & db) : _db{db} {}
|
||||
|
||||
MOCK_CONST_METHOD0(displayName, std::string_view());
|
||||
MOCK_CONST_METHOD0(path, std::string_view());
|
||||
MOCK_CONST_METHOD0(parent, Category *());
|
||||
MOCK_CONST_METHOD2(create, std::unique_ptr< Category >(std::string, std::string));
|
||||
MOCK_CONST_METHOD0(children, std::unique_ptr< CategoriesChildren >());
|
||||
MOCK_CONST_METHOD0(id, int64_t());
|
||||
|
||||
void _init_simple(std::string name) {
|
||||
_root_guard();
|
||||
_createChild(_root_id, name);
|
||||
_createChild(_id, name);
|
||||
}
|
||||
|
||||
void _initRoot() {
|
||||
using namespace testing;
|
||||
const auto & row = _db(sqlpp::postgresql::insert_into(t_category) //
|
||||
.set(t_category.name = "root", //
|
||||
t_category.parent_id = sqlpp::null,
|
||||
t_category.owner = sqlpp::verbatim< sqlpp::integer >(" app_current_user_id() "))
|
||||
.returning(t_category.id, t_category.parent_path))
|
||||
.front();
|
||||
.set(t_category.name = "root", //
|
||||
t_category.parent_id = sqlpp::null,
|
||||
t_category.owner = sqlpp::verbatim< sqlpp::integer >(" app_current_user_id() "))
|
||||
.returning(t_category.id, t_category.parent_path))
|
||||
.front();
|
||||
|
||||
_root_id = row.id;
|
||||
_path = row.parent_path;
|
||||
_id = row.id;
|
||||
_path = row.parent_path;
|
||||
}
|
||||
|
||||
void _expect_call_path() {
|
||||
void _expect_call_id() {
|
||||
using namespace testing;
|
||||
EXPECT_CALL(*this, path()).WillRepeatedly(Return(_path));
|
||||
EXPECT_CALL(*this, id()).WillRepeatedly(Return(_id));
|
||||
}
|
||||
|
||||
private:
|
||||
Connection & _db;
|
||||
int64_t _root_id{0};
|
||||
int64_t _id{0};
|
||||
std::string _path;
|
||||
};
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ struct CategoriesImpl::CategoriesImplPriv {
|
||||
};
|
||||
|
||||
CategoriesImpl::CategoriesImpl(std::unique_ptr< std::vector< std::unique_ptr< Category > > > data)
|
||||
: eedb::Categories(boost::make_transform_iterator(data->begin(), CategoriesImplPriv::getTransform()),
|
||||
: eedb::CategoriesChildren(boost::make_transform_iterator(data->begin(), CategoriesImplPriv::getTransform()),
|
||||
boost::make_transform_iterator(data->end(), CategoriesImplPriv::getTransform())),
|
||||
_priv{spimpl::make_unique_impl< CategoriesImplPriv >(std::move(data))} {}
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@ struct CategoryImpl::CategoryImplPrivate {
|
||||
std::string _description;
|
||||
};
|
||||
|
||||
CategoryImpl::CategoryImpl(Connection &db) : _priv{spimpl::make_impl< CategoryImplPrivate >(db, nullptr)} {
|
||||
CategoryImpl::CategoryImpl(Connection & db) : _priv{spimpl::make_impl< CategoryImplPrivate >(db, nullptr)} {
|
||||
_priv->_self = this;
|
||||
}
|
||||
|
||||
@ -138,15 +138,11 @@ Category::string_view CategoryImpl::displayName() const {
|
||||
return _priv->displayName();
|
||||
}
|
||||
|
||||
Category::string_view CategoryImpl::path() const {
|
||||
return _priv->path();
|
||||
}
|
||||
|
||||
Category * CategoryImpl::parent() const {
|
||||
return _priv->parent();
|
||||
}
|
||||
|
||||
std::unique_ptr< Categories > CategoryImpl::children() const {
|
||||
std::unique_ptr< CategoriesChildren > CategoryImpl::children() const {
|
||||
return std::make_unique< CategoriesImpl >(_priv->categories());
|
||||
}
|
||||
|
||||
@ -154,4 +150,8 @@ std::unique_ptr< Category > CategoryImpl::create(std::string name, std::string d
|
||||
return _priv->create(std::move(name), std::move(description));
|
||||
}
|
||||
|
||||
int64_t CategoryImpl::id() const {
|
||||
return _priv->id();
|
||||
}
|
||||
|
||||
} // namespace eedb::pg
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include <eedb/pg/Item.hpp>
|
||||
|
||||
#include <eedb/Category.hpp>
|
||||
#include <eedb/Value.hpp>
|
||||
#include <eedb/pg/Category.hpp>
|
||||
|
||||
#include <eedb/pg/connection.hpp>
|
||||
#include <eedb/pg/model/all.hpp>
|
||||
@ -15,16 +15,12 @@ namespace eedb::pg {
|
||||
struct ItemImpl::ItemPriv {
|
||||
ItemPriv(Connection & db, int64_t uid, item::Attributes attributes) : _db{db}, _uid{uid}, _attributes{std::move(attributes)} {}
|
||||
|
||||
bool attachToCategory(const Category * category) {
|
||||
bool attachToCategory(const Category * _category) {
|
||||
auto category = dynamic_cast< const CategoryImpl * >(_category);
|
||||
assert(category);
|
||||
auto x = sqlpp::cte(sqlpp::alias::x)
|
||||
.as(select(t_category.parent_id) //
|
||||
.from(t_category) //
|
||||
.where(t_category.parent_path == std::string{category->path()})
|
||||
.limit(1u));
|
||||
|
||||
_db(insert_into(t_category_items) //
|
||||
.set(t_category_items.category_id = 1, t_category_items.item_id = _uid));
|
||||
.set(t_category_items.category_id = category->id(), t_category_items.item_id = _uid));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -38,10 +38,10 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv {
|
||||
return std::tuple_cat(insert(attributes.values()), insert_producer(attributes.producer()));
|
||||
}
|
||||
|
||||
auto insert(const item::Identyfier &id, item::Attributes attributes, const std::optional< item::Foto > & foto) {
|
||||
auto insert(const item::Identyfier & id, item::Attributes attributes, const std::optional< item::Foto > & foto) {
|
||||
try {
|
||||
auto uid = _db(sqlpp::postgresql::insert_into(t_item) //
|
||||
.set(std::tuple_cat( //
|
||||
auto uid = _db(sqlpp::postgresql::insert_into(t_item) //
|
||||
.set(std::tuple_cat( //
|
||||
insert(id),
|
||||
insert(attributes))) //
|
||||
.returning(t_item.id))
|
||||
@ -84,14 +84,6 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv {
|
||||
}
|
||||
}
|
||||
|
||||
auto _cte_categoryIdByPath(const ItemQueryFilters & filer) const {
|
||||
return sqlpp::cte(sqlpp::alias::x)
|
||||
.as(select(t_category.parent_id) //
|
||||
.from(t_category) //
|
||||
.where(t_category.parent_path == std::string{filer.category() ? filer.category()->path() : std::string_view{""}})
|
||||
.limit(1u));
|
||||
}
|
||||
|
||||
auto _titem() const {
|
||||
return t_item.inner_join(t_category_items).on(t_item.id == t_category_items.item_id);
|
||||
}
|
||||
@ -120,18 +112,16 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv {
|
||||
auto search(const ItemQueryFilters & filer) {
|
||||
using sqlpp::dynamic_select;
|
||||
|
||||
auto x = _cte_categoryIdByPath(filer);
|
||||
|
||||
auto s = dynamic_select(_db.native(), all_of(t_item)) //
|
||||
.dynamic_from(_titem()) //
|
||||
.dynamic_where()
|
||||
.limit(100u);
|
||||
|
||||
if(filer.category() != nullptr) {
|
||||
s.where.add(t_category_items.category_id == select(x.parent_id).from(x));
|
||||
if(auto cat = dynamic_cast< const CategoryImpl * >(filer.category()); cat != nullptr) {
|
||||
s.where.add(t_category_items.category_id == cat->id());
|
||||
}
|
||||
|
||||
auto rows = _db(with(x)(s));
|
||||
auto rows = _db(s);
|
||||
|
||||
_items.clear();
|
||||
for(const auto & row : rows) {
|
||||
|
||||
@ -27,5 +27,4 @@ TEST_F(PgCategoriesRepositoryTest, rootNotNull) {
|
||||
auto root = sut->root();
|
||||
ASSERT_TRUE(root);
|
||||
EXPECT_FALSE(root->parent());
|
||||
EXPECT_EQ(root->path(), "root");
|
||||
}
|
||||
|
||||
@ -31,6 +31,11 @@ TEST_F(PgCategoryTest, rootCategoryHasNoParent) {
|
||||
EXPECT_FALSE(sut->parent());
|
||||
}
|
||||
|
||||
TEST_F(PgCategoryTest, id) {
|
||||
auto category = sut->create("name", "description");
|
||||
EXPECT_NE(dynamic_cast< eedb::pg::CategoryImpl * >(category.get())->id(), 0);
|
||||
}
|
||||
|
||||
TEST_F(PgCategoryTest, createChild) {
|
||||
sut->create("name", "description");
|
||||
auto children = sut->children();
|
||||
@ -54,8 +59,3 @@ TEST_F(PgCategoryTest, childHasParent) {
|
||||
EXPECT_EQ(child->parent(), sut.get());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PgCategoryTest, path) {
|
||||
auto path = std::string{sut->create("name", "description")->create("name", "description")->path()};
|
||||
EXPECT_THAT(path, MatchesRegex(R"(root\.[0-9]*\.[0-9]*)"));
|
||||
}
|
||||
|
||||
@ -37,7 +37,8 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > {
|
||||
EXPECT_CALL(textParameter, name()).WillRepeatedly(Return(std::string_view{"text parameter"}));
|
||||
EXPECT_CALL(listParameter, name()).WillRepeatedly(Return(std::string_view{"list parameter"}));
|
||||
|
||||
return eedb::Values(eedb::Value{5, &numericParameter},
|
||||
return eedb::Values( //
|
||||
eedb::Value{5, &numericParameter},
|
||||
eedb::Value{"some text"s, &textParameter},
|
||||
eedb::Value{std::vector{1.2, 3.4, 5.6, 7.8}, &listParameter});
|
||||
}
|
||||
@ -68,6 +69,6 @@ TEST_F(PgItemsRepositoryTest, createTwiceThrowsException) {
|
||||
|
||||
TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) {
|
||||
EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {}));
|
||||
category._expect_call_path();
|
||||
category._expect_call_id();
|
||||
auto items = sut->search(eedb::ItemQueryFilters{&category});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user