Repository: proteanhq/protean

Issue:
Add support for `update_all` and `delete_all` methods that ignore Entity Callbacks

Discussion:
codecov-io: # [Codecov](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=h1) Report
> Merging [#108](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=desc) into [master](https://codecov.io/gh/proteanhq/protean/commit/b7c680be45ac71c4169c99aa196360db4685ec1e?src=pr&el=desc) will **decrease** coverage by `0.15%`.
> The diff coverage is `81.48%`.

[![Impacted file tree graph](https://codecov.io/gh/proteanhq/protean/pull/108/graphs/tree.svg?width=650&token=0sFuFdLBOx&height=150&src=pr)](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #108      +/-   ##
==========================================
- Coverage   82.67%   82.51%   -0.16%     
==========================================
  Files          41       41              
  Lines        2095     2105      +10     
  Branches      313      311       -2     
==========================================
+ Hits         1732     1737       +5     
- Misses        244      247       +3     
- Partials      119      121       +2
```


| [Impacted Files](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/protean/core/repository/base.py](https://codecov.io/gh/proteanhq/protean/pull/108/diff?src=pr&el=tree#diff-c3JjL3Byb3RlYW4vY29yZS9yZXBvc2l0b3J5L2Jhc2UucHk=) | `90.54% <100%> (+0.26%)` | :arrow_up: |
| [src/protean/core/entity.py](https://codecov.io/gh/proteanhq/protean/pull/108/diff?src=pr&el=tree#diff-c3JjL3Byb3RlYW4vY29yZS9lbnRpdHkucHk=) | `91.05% <76.92%> (-0.62%)` | :arrow_down: |
| [src/protean/impl/repository/dict\_repo.py](https://codecov.io/gh/proteanhq/protean/pull/108/diff?src=pr&el=tree#diff-c3JjL3Byb3RlYW4vaW1wbC9yZXBvc2l0b3J5L2RpY3RfcmVwby5weQ==) | `98.34% <83.33%> (-1.11%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=footer). Last update [b7c680b...4fdacb1](https://codecov.io/gh/proteanhq/protean/pull/108?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/docs/conf.py b/docs/conf.py
index 5174c73a..2b14a639 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -23,7 +23,7 @@ if os.getenv('SPELLCHECK'):
 source_suffix = '.rst'
 master_doc = 'index'
 project = 'Protean'
-year = '2018'
+year = '2019'
 author = 'Subhash Bhushan C'
 copyright = '{0}, {1}'.format(year, author)
 version = release = '0.0.9'
@@ -41,7 +41,7 @@ extlinks = {
 #     html_theme = 'alabaster'
 
 # Change theme to Alabaster
-html_theme = 'alabaster'
+html_theme = 'sphinx_rtd_theme'
 
 html_use_smartypants = True
 html_last_updated_fmt = '%b %d, %Y'
diff --git a/docs/index.rst b/docs/index.rst
index dea4a8b4..c09242d4 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,30 +30,31 @@ Release v\ |version|. (:ref:`Installation <install>`)
 
 It is a great fit for you if you are:
 
-- Building robust, mission-critical applications for complex domains
+- Building robust, mission-critical applications for complex and uncharted domains
 - Porting complicated Legacy applications onto newer technology stacks
-- Creating products to adapt and evolve over long cycles
+- Creating innovative products that will adapt and evolve over long cycles
 
 *Protean is free, open source, and always will be.*
 
 .. warning:: **Protean** is currently under active development. APIs and Interfaces are to be expected to change drastically and newer releases will almost certainly be backward incompatible. If you are interested in using Protean for your project, you may want to wait for the first stable production-ready version 0.1.0. If you want to use the framework *right now*, drop us an `email <subhash@team8solutions.com>`_.
 
-Beloved Features
-----------------
+Key Features
+------------
 
-Protean is ready for today's diverse software stack requirements.
+Protean is ready for today's diverse and layered software stack requirements:
 
-- Out-of-the-box database support for Elasticsearch and everything that is accessible through SQLAlchemy.
 - Lightweight APIs
-- Helper packages like Authentic that take care of end-to-end authentication
+- Non-opinionated and non-enforcing Application Code organization
+- Abstract implementations for well-understood design patterns
+- Expressive Domain Language for both developers as well as Business Users
+- Full support for Domain-Driven Design
+- Out-of-the-box database support for SQL and NoSQL Databases
+- Ready to use plugins for popular API frameworks like Flask and Pyramid
+- Extendable interfaces to build your own plugins
+- Concrete Implementations for typical Business requirements like Authentication and Notifications
 
 Protean officially supports Python 3.6+.
 
-Why we built Protean
---------------------
-
-This reason why we built Protean and the thought-process behind its choices is explained here.
-
 .. toctree::
     :maxdepth: 1
     :caption: Philosophy
@@ -62,20 +63,10 @@ This reason why we built Protean and the thought-process behind its choices is e
     philosophy/decision-delay
     philosophy/architecture/dependency-rule
 
-The User Guide
---------------
-
-This part of the documentation introduces some background information about protean, then focuses on step-by-step instructions for getting the most out of Protean.
-
-.. note:: Protean's test code is littered with usage of a certain `Dog` class. If you find that discomforting, replace `Dog` with `CuteLittlePuppyDog` everywhere.
-
-    **Disclosure**: No real dog was harmed in the process of building this framework.
-
 .. toctree::
    :maxdepth: 2
    :caption: User Guide
 
-   user/intro
    user/install
    user/quickstart
    user/entities
diff --git a/docs/philosophy/why-protean.rst b/docs/philosophy/why-protean.rst
index 92e3f99e..d03dc1b3 100644
--- a/docs/philosophy/why-protean.rst
+++ b/docs/philosophy/why-protean.rst
@@ -3,7 +3,22 @@
 Why Protean?
 ============
 
-Most of us have developed applications, for everything from weekend projects to SaaS software, using popular frameworks meant to ease our development effort and reduce our go-live time. And the frameworks do deliver, and sometimes wonderously, on the promise of shortening the timeframe and providing constructs to do almost everything. But when we attempt to take the same knowledge and build an application to address the needs of a complex domain, things tend to break down. Such applications tend to have long product cycles, usually over multiple years, and also evolve over time as we go deeper and deeper into the domain. To our chagrin, we discover that while we were able to get the first version of the product out of the door relatively quickly, things tend to become complicated over time. And instead of speeding up as we disover and understand more about the business, development tends to slow down and get costlier. In extreme cases, the product can literally come to a stand still with developers just to trying to fight entropy and keep the product running.
+Would you buy a car if someone told you that you would have to replace the entire car if you tear a chair cushion?
+
+We see plenty of examples around us of design architectures built for flexibility and maintainability:
+
+* Components work very well with each other yet are not tightly coupled. You can disassemble most of them, though disassembling some may be vastly more complex than others (Say an automobile engine)
+* Each component adheres to a well-understood, well-published contract. So as long as the "contract" is fulfilled, a component can be replaced with its competitor's parts.
+
+You see this feature repeating in most physical products - Cars, Laptops, Furniture, Kitchen Equipment and the list goes on. Want to enter a market for rubber gaskets? Just look up the contract (dimensions, quality, durability, etc.), fulfill them in your product at the lowest cost possible, and you are on. Marketing your product to get into the hands of the consumer is an entirely different story, but creating a new product is relatively simple.
+
+This thought process does exist in the software industry, but to a far lesser extent.
+
+We see this breakage when we try to switch to a new technology because it has made a task cheaper/simpler, or a competitor because he is offering better rates or better functionality, or simply because a component is outdated and non-maintained. As a developer, you would typically spend more time rewriting code to switch to the new component, than you spent actually writing it in the first place. More importantly,you probably will expend the same effort when you decide to switch the component again in the future.
+
+Most of us have developed applications, for everything from weekend projects to SaaS software, using popular frameworks meant to ease our development effort and reduce our go-live time. The frameworks promise shorter timeframes and better output, and deliver on the promise more often than not. But when we attempt to take the same knowledge and build an application to address the needs of a complex domain, things tend to break down. Such applications tend to have long product cycles, usually over multiple years, and also evolve over time as we go deeper and deeper into the domain.
+
+To our chagrin, we discover that while we were able to get the first version of the product out of the door relatively quickly, things tend to become complicated over time. And instead of speeding up as we discover and understand more about the business, development tends to slow down and get costlier. In extreme cases, the product can literally come to a stand still with developers just to trying to fight entropy and keep the product running.
 
 Protean was built with the vision of providing a clear path to creating and maintaining such complex applications. In that sense, it is a Thought framework rather than a technology framework. It advocates a domain-centric thought process, usage of well-thought design patterns, code organization, separation of concerns and adopting a common language spoken by all stakeholders of a project. The technology constructs offered are a means to and end, to make the above facets possible.
 
@@ -17,39 +32,43 @@ Irrespective of which option you use Protean for, you end up with cutting-edge p
 * Established Design Patterns to organize your code for maintainability
 * 100% Testability of your business logic
 
-As a Domain-Driven Design Framework
------------------------------------
-
-**WIP**
+Protean as a Domain-Driven Design Framework
+-------------------------------------------
 
-Protean is also pragmatic at the same time. It does not ignore or skirt-around realities of performance or technology limitations, and tries to provide a wide variety of options to address realworld, production-site issues.
+Domain-Driven Design is a software development technique that places the understanding of customer’s problem domain at the heart of software. It is a bundle of both technical ideas as well as a reliable process structure the creativity in the development cycle.
 
-As a Clean Architecture Framework
----------------------------------
+Protean helps drive this creative process, assisting the developers and business experts to converge on a Domain Model, using a common Ubiquitous language. It relieves the developer of the burden to develop an end-to-end prototype in the product and allows him to focus on mirroring the domain model in the product, tested with real use-cases and gathering feedback along the way. It strengthens the iterative process of model refinement until the domain model adequately reflects the problem domain, focusing on the important aspects and leaving out irrelevant ones.
 
-Much of what follows has been outlined in |uncle-bob-article|, but I will reiterate the core philosophy for everyone's benefit.
+The unimportant aspects during model refinement include infrastructure details like database, API framework, storage, etc. Protean lets you refine the model first and then plugin an infrastructure component dynamically into the codebase. By virtue of delaying infrastructure decisions until needed, developers tend to make a more informed decision of the correct technology appropriate for the problem statement.
 
-.. |uncle-bob-article| raw:: html
+Protean is also pragmatic at the same time. It does not ignore or skirt-around realities of performance or technology limitations, and tries to provide a wide variety of options to address realworld, production concerns.
 
-    <a href="http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank">Uncle Bob's article</a>
+Protean as a Clean Architecture Framework
+-----------------------------------------
 
-Clean Architecture as an idea is not new. There have been similar architectures outlined by various people like, Hexagonal Architecture, Onion Architecture, Screaming Architecture, and
-Lean Architecture.
+Clean Architecture is not a new idea. There have been similar architectures outlined by various people like, Hexagonal Architecture, Onion Architecture, Screaming Architecture, and Lean Architecture.
 
-Though these architectures all vary somewhat in their details, they are very similar. They all have the same objective, which is the separation of concerns. They all achieve this separation by dividing the software into layers. Each has at least one layer for business rules, and another for interfaces.
+Though these architectures vary to some extent in their details, they are all focused on the single goal of separation of concerns. They achieve this separation by dividing the codebase into layers. Each has at least one layer designated for business rules, and one or more layers for interfaces to infrastructure technology.
 
-An application built with Clean Architecture system would typically be:
+An application built with Clean Architecture system is 
 
 * **Independent of Frameworks**: Application does not depend on the existence of some library of feature laden software. This allows the application to use such frameworks as tools, rather than having to shoe-horn the functionality into their limited constraints.
 * **Testable**: The Application's business rules can be tested without the UI, Database, Web Server, or any other external element, making it faster, dependable and resitant to external changes
-* **Independent of UI**: The UI of the application (or UIs, if multiple channels like Mobiles are involved) can change easily, without needing any changes to the rest of the system. A user should be able to use a console UI, in need be, without changing the business rules.
-* **Independent of Database**: The application's business rules are not bound to the database. You can swap out one SQL database for another, or even switch to a NoSQL DB like Mongo, BigTable, CouchDB or Elasticsearch!
+* **Independent of UI or database constraints**: The UI of the application (or UIs, if multiple channels like Mobiles are involved) can change easily, without needing any changes to the rest of the system. A user should be able to use a console UI, in need be, without changing the business rules. Similarly, the application's business rules are not bound to the database. You can swap out one SQL database for another, or even switch to a NoSQL DB like Mongo, BigTable, CouchDB or Elasticsearch.
 * **Independent of any external agency**: The application is basically agnostic to the outside world. The business rules simply don’t know anything at all about what it's like out there.
 
-By being independent, an application allows developers to delay taking long-term decisions until the last possible moment.
+By being independent, an application allows developers to delay long-term decisions until the last possible moment.
 
-What is a long-term decision? Anything that needs considerable time and effort to change, like the choice of a database or a web framework, or even the data format of messages between the backend and the UI, is considered a long-term decision. And what does a last possible moment look like? Any time frame beyond which not making a decision results in diminishing returns or declining productivity. As they say, sometime's a bad decision is much better than no decision at all. 
+A long term decision is any part of the design that needs considerable time and effort to change, like the choice of a database or a web framework, or even the data format of messages between the backend and the UI. The last possible moment is any time frame beyond which not making a decision results in diminishing returns or declining productivity. As they say, sometime's a bad decision is much better than no decision at all.
 
 But the real beauty of a Clean Architecture compliant application would be that even after you have taken long-term decisions at the last possible moment, you can still go back to the blackboard and start anew, without spending a ton of time and effort. That's where interface definitions play a critical role. As long as your components adhere to the contract published by the application, you can switch between them freely and often, on the fly.
 
-Protean is an application framework geared to get you on board the Clean Architecture wagon from day one. It was built based on learning and feedback while building applications for realworld clients. Unknown requirements, changing technology landscape, improved API communication and ever tighter deadlines pushed us to wonder if there was a way to build an application where all these factors could be addressed. Where we could actually go back on a decison and switch to a better solution in the middle of a project, without costing the project a tooth or a limb.
+Protean is geared to get you on board the Clean Architecture wagon from day one. It was built based on learning and feedback while building applications for realworld clients. Unknown requirements, changing technology landscape, improved API communication and ever tighter deadlines pushed us to wonder if there was a way to build an application where all these factors could be addressed. Where we could actually go back on a decison and switch to a better solution in the middle of a project, without costing the project a tooth or a limb.
+
+Protean is geared for flexibility and maintainability for the long run.
+
+More on clean architecture has been outlined in |uncle-bob-article|.
+
+.. |uncle-bob-article| raw:: html
+
+    <a href="http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank">Uncle Bob's article</a>
diff --git a/docs/requirements.txt b/docs/requirements.txt
index d18def6e..ebb15ba7 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,2 +1,3 @@
 sphinx>=1.3
+sphinx_rtd_theme>=0.4.3
 -e .
diff --git a/docs/user/intro.rst b/docs/user/intro.rst
deleted file mode 100644
index 13573629..00000000
--- a/docs/user/intro.rst
+++ /dev/null
@@ -1,35 +0,0 @@
-.. _introduction:
-
-Introduction
-============
-
-In Short...
------------
-
-Protean allows your application to be:
-
-* **Independent of Frameworks**: The philosophy is important, not the implementation. You don't necessarily depend on "Protean" library, as well. Protean is a just a lightweight collection of base classes and interfaces that will help you get on with your application development, faster.
-* **Flexible**: Do gravity defying, brain-twisting, dangerous stunts like switching databases, writing into different databases at the same time, moving across to faster web frameworks etc. all this while not rewriting even one line of existing code.
-* **Testable**: 100% coverage is not a mirage anymore.
-* **Independent of Implementation Details** (like UI, Database, Cache, and Messaging Medium): You don't have to decide on your application stack on day one. And when you do decide, you can  change your mind again!
-
-The Long Version
-----------------
-
-Would you buy a car if someone told you that you would have to replace the entire car if you tear a chair cushion?
-
-Everywhere around us, we see examples of product architectures built for replaceability. Components work very well with each other yet are not tightly coupled. Each component adheres to a well-understood, well-published contract. So as long as the "contract" is fulfilled, a component can be replaced with its competitor's parts. You see this in Physical products like Cars, Laptops, Furniture, Kitchen Equipment and list goes on. Want to enter a market for rubber gaskets? Just look up the contract (dimensions, quality, durability), fulfill them in your product at the lowest cost possible, and you are on. Marketing that is necessary to get your product into the hands of the consumer is an entirely different story, but creating a new product is relatively simple.
-
-Somehow this thought process has not been prevalent in the software industry. Yes, we do have a few excellent examples, but they are few and far in between. When one builds an application, all components are supposed to live their life out together, until they all die out. Forget about replacing a faulty component or switching to a better component.
-
-Let's take another example. What if you wanted to change a specific piece of your software application. It could be because technology changes have made a task cheaper/simpler, a competitor of a component you use is offering better rates for the same functionality, or the component has not kept up with the times and is dying a slow painful death due to non-maintainability. As a developer, would you want to plug in the new component or would you want to spend some (considerable?) effort of time rewriting code to switch to the new component? More importantly, what happens the next time you decide to change the component again?
-
-Clean architecture not only allows you to design applications with very low coupling and independent of technical implementation details (think databases and frameworks), it also makes applications easy to maintain and flexible to change. Plus applications become intrinsically testable. Think 100% coverage. Does that not sound like a dream?
-
-Uncle Bob presents a solid case for Clean Architecture on his |bob_blog|. However, the idea itself is not new. The central focus of the philosophy is to ensure that the dependencies between components are correctly arranged and to ensure all implementation details adhere to a set of contracts (Think Interfaces, Plugins, Adapters.)
-
-Protean attempts to mainstream this idea while ensuring that the entry bar for a development team just starting on their clean architecture journey is low. While it espouses the idea of a plugin-based architecture, it also supplies adapters out of the box for most popular technical implementations (Think Databases, Web Frameworks, Messaging Mediums, and Cache Providers). Protean does not attempt to replace any of these components; it just tries to make you avoid getting locked into them. If you ever want to switch a technical implementation into some other product, you are covered from day one.
-
-.. |bob_blog| raw:: html
-
-   <a href="http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank">blog</a>
\ No newline at end of file
diff --git a/src/protean/core/entity.py b/src/protean/core/entity.py
index 65bee4ca..9def2851 100644
--- a/src/protean/core/entity.py
+++ b/src/protean/core/entity.py
@@ -361,7 +361,7 @@ class QuerySet:
         """Updates all objects with details given if they match a set of conditions supplied.
 
         This method forwards filters and updates directly to the adapter. It does not instantiate
-        models and it does not trigger Entity callbacks or validations.
+        entities and it does not trigger Entity callbacks or validations.
 
         Update values can be specified either as a dict, or keyword arguments.
 
@@ -378,6 +378,24 @@ class QuerySet:
 
         return updated_item_count
 
+    def delete_all(self, *args, **kwargs):
+        """Deletes objects that match a set of conditions supplied.
+
+        This method forwards filters directly to the adapter. It does not instantiate entities and
+        it does not trigger Entity callbacks or validations.
+
+        Returns the number of objects matched and deleted.
+        """
+        deleted_item_count = 0
+        _, adapter = self._retrieve_model()
+        try:
+            deleted_item_count = adapter._delete_all_objects(self._criteria)
+        except Exception as exc:
+            # FIXME Log Exception
+            raise
+
+        return deleted_item_count
+
     ###############################
     # Python Magic method support #
     ###############################
@@ -883,23 +901,22 @@ class Entity(metaclass=EntityBase):
     def delete(self):
         """Delete a Record from the Repository
 
-        Throws ObjectNotFoundError if the object was not found in the repository
-        """
-        # FIXME: Ensure Adapter throws ObjectNotFoundError
+        will perform callbacks and run validations before deletion.
 
+        Throws ObjectNotFoundError if the object was not found in the repository.
+        """
         # Fetch Model class and connected-adapter from Repository Factory
-        _, adapter = self.__class__._retrieve_model()
+        model_cls, adapter = self.__class__._retrieve_model()
 
-        filters = {
-            self.id_field.field_name: getattr(self, self.id_field.field_name)
-        }
         try:
-            count_deleted = adapter._delete_objects(**filters)
+            if not self.is_destroyed:
+                # Update entity's data attributes
+                adapter._delete_object(model_cls.from_entity(self))
 
-            # Mark as Destroyed
-            self._state.mark_destroyed()
+                # Set Entity status to saved
+                self._state.mark_destroyed()
 
-            return count_deleted
+            return self
         except Exception as exc:
             # FIXME Log Exception
             raise
diff --git a/src/protean/core/repository/base.py b/src/protean/core/repository/base.py
index 32254636..35a5bb1e 100644
--- a/src/protean/core/repository/base.py
+++ b/src/protean/core/repository/base.py
@@ -60,7 +60,11 @@ class BaseAdapter(RegisterLookupMixin, metaclass=ABCMeta):
         """Updates object directly in the repository and returns update count"""
 
     @abstractmethod
-    def _delete_objects(self, **filters):
+    def _delete_object(self):
+        """Delete a Record from the Repository"""
+
+    @abstractmethod
+    def _delete_all_objects(self, criteria: Q):
         """Delete a Record from the Repository"""
 
 
diff --git a/src/protean/impl/repository/dict_repo.py b/src/protean/impl/repository/dict_repo.py
index af9579e4..e0d431fc 100644
--- a/src/protean/impl/repository/dict_repo.py
+++ b/src/protean/impl/repository/dict_repo.py
@@ -154,26 +154,30 @@ class Adapter(BaseAdapter):
 
         return update_count
 
-    def _delete_objects(self, **filters):
-        """ Delete the dictionary object by its id"""
+    def _delete_object(self, model_obj):
+        """ Delete the entity record in the dictionary """
+        identifier = model_obj[self.entity_cls.id_field.field_name]
+        with self.conn['lock']:
+            # Check if object is present
+            if identifier not in self.conn['data'][self.model_name]:
+                raise ObjectNotFoundError(
+                    f'`{self.__class__.__name__}` object with identifier {identifier} '
+                    f'does not exist.')
 
-        # Delete the object from the dictionary and return the deletion count
-        delete_ids = []
-        for identifier, item in self.conn['data'][self.model_name].items():
-            match = True
+            del self.conn['data'][self.model_name][identifier]
+        return model_obj
 
-            # Add objects that match the given filters
-            for fk, fv in filters.items():
-                if item[fk] != fv:
-                    match = False
-            if match:
-                delete_ids.append(identifier)
+    def _delete_all_objects(self, criteria: Q):
+        """ Delete the dictionary object by its criteria"""
+
+        # Delete the object from the dictionary and return the deletion count
+        items = self._filter(criteria, self.conn['data'][self.model_name])
 
         # Delete all the matching identifiers
-        for identifier in delete_ids:
-            del self.conn['data'][self.model_name][identifier]
+        for identifier in items:
+            self.conn['data'][self.model_name].pop(identifier, None)
 
-        return len(delete_ids)
+        return len(items)
 
     def delete_all(self):
         """ Delete all objects in this schema """


Test patch:
diff --git a/tests/core/test_entity.py b/tests/core/test_entity.py
index 50f8f676..59d055c4 100644
--- a/tests/core/test_entity.py
+++ b/tests/core/test_entity.py
@@ -547,15 +547,38 @@ class TestEntity:
     def test_delete(self):
         """ Delete an object in the reposoitory by ID"""
         dog = Dog.create(id=3, name='Johnny', owner='Carey')
-        del_count = dog.delete()
-        assert del_count == 1
+        deleted_dog = dog.delete()
+        assert deleted_dog is not None
+        assert deleted_dog.is_destroyed is True
 
-        del_count = dog.delete()
-        assert del_count == 0
+        with pytest.raises(ObjectNotFoundError):
+            Dog.get(3)
+
+    def test_delete_all(self):
+        """Try updating all records satisfying filter in one step, passing a dict"""
+        Dog.create(id=1, name='Athos', owner='John', age=2)
+        Dog.create(id=2, name='Porthos', owner='John', age=3)
+        Dog.create(id=3, name='Aramis', owner='John', age=4)
+        Dog.create(id=4, name='dArtagnan', owner='John', age=5)
+
+        # Perform update
+        deleted_count = Dog.query.filter(age__gt=3).delete_all()
+
+        # Query and check if only the relevant records have been deleted
+        assert deleted_count == 2
+
+        dog1 = Dog.get(1)
+        dog2 = Dog.get(2)
+
+        assert dog1 is not None
+        assert dog2 is not None
 
         with pytest.raises(ObjectNotFoundError):
             Dog.get(3)
 
+        with pytest.raises(ObjectNotFoundError):
+            Dog.get(4)
+
     def test_delete_by(self):
         """Test that update by query updates only correct records"""
         Dog.create(id=1, name='Athos', owner='John', age=2)
diff --git a/tests/core/test_repository.py b/tests/core/test_repository.py
index 52711c5a..ad7e35a4 100644
--- a/tests/core/test_repository.py
+++ b/tests/core/test_repository.py
@@ -103,11 +103,9 @@ class TestRepository:
     def test_delete(self):
         """ Delete an object in the reposoitory by ID"""
         dog = Dog.create(id=3, name='Johnny', owner='Carey')
-        del_count = dog.delete()
-        assert del_count == 1
-
-        del_count = dog.delete()
-        assert del_count == 0
+        deleted_dog = dog.delete()
+        assert deleted_dog is not None
+        assert deleted_dog.is_destroyed is True
 
         with pytest.raises(ObjectNotFoundError):
             Dog.get(3)