Repository: makridenko/supadantic

Issue:
`delete` method
```python
user = User()
user.save()
user.delete()
```

Discussion:

Patch:
diff --git a/README.md b/README.md
index c272146..f4b9ee8 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,9 @@ User.get_list(neq={'name': 'Another name'})
 # Get one user
 user = User.get(eq={'id': 1})
 
+# Delete this user
+user.delete()
+
 # Bulk update
 User.bulk_update(ids=[1,2], data={'name': 'New name'})
 ```
diff --git "a/\\" "b/\\"
new file mode 100644
index 0000000..c619148
--- /dev/null
+++ "b/\\"
@@ -0,0 +1,112 @@
+from unittest.mock import MagicMock, Mock, PropertyMock
+
+import pytest
+from pytest_mock import MockerFixture
+
+from supadantic.supabase_client import SupabaseClient
+
+
+class TestSupabaseClient:
+    @pytest.fixture(autouse=True)
+    def mock_create_client(self, mocker: MockerFixture) -> MagicMock:
+        return mocker.patch('supadantic.supabase_client.create_client')
+
+    @pytest.fixture
+    def supabase_client(self) -> SupabaseClient:
+        return SupabaseClient(table_name='table_name')
+
+    def test_insert(self, supabase_client: SupabaseClient):
+        # Prepare data
+        mock_supabase_query = Mock()
+
+        supabase_client.query = mock_supabase_query
+
+        test_data = {'test': 'data'}
+
+        mock_response = Mock()
+        type(mock_response).data = PropertyMock(return_value=[test_data])
+
+        mock_supabase_query.insert.return_value.execute.return_value = mock_response
+
+        # Execution
+        response = supabase_client.insert(test_data)
+
+        # Testing
+        mock_supabase_query.insert.assert_called_once_with(test_data)
+        assert response == test_data
+
+    def test_update(self, supabase_client: SupabaseClient):
+        # Prepare data
+        mock_supabase_query = Mock()
+
+        supabase_client.query = mock_supabase_query
+
+        test_data = {'test': 'data'}
+        test_data_with_id = {'id': 1, 'test': 'data'}
+
+        mock_response = Mock()
+        type(mock_response).data = PropertyMock(return_value=[test_data_with_id])
+
+        mock_supabase_query.update.return_value.eq.return_value.execute.return_value = mock_response
+
+        # Execution
+        response = supabase_client.update(id=1, data=test_data)
+
+        # Testing
+        mock_supabase_query.update.assert_called_once_with(test_data)
+        mock_supabase_query.update.return_value.eq.assert_called_once_with('id', 1)
+
+        assert response == test_data_with_id
+
+    def test_select(self, supabase_client: SupabaseClient):
+        # Prepare data
+        mock_supabase_query = Mock()
+
+        supabase_client.query = mock_supabase_query
+
+        test_filters = {'column1': 'value1', 'column2': 'value2'}
+
+        mock_response = Mock()
+        type(mock_response).data = PropertyMock(return_value=[{'id': 1}, {'id': 2}])
+
+        mock_supabase_query.select.return_value.eq.return_value.eq.return_value.execute.return_value = mock_response
+
+        # Execution
+        result = supabase_client.select(eq=test_filters)
+
+        # Testing
+        mock_supabase_query.select.assert_called_with('*')
+
+        mock_supabase_query.select.return_value.eq.assert_called_with('column1', 'value1')
+        mock_supabase_query.select.return_value.eq.return_value.eq.assert_called_with('column2', 'value2')
+
+        # Assert the result
+        assert result == [{'id': 1}, {'id': 2}]
+
+    def test_bulk_update(self, supabase_client: SupabaseClient):
+        # Prepare data
+        mock_supabase_query = Mock()
+
+        supabase_client.query = mock_supabase_query
+
+        test_data = {'name': 'new_name'}
+        test_ids = [1, 2, 3]
+        test_response = [
+            {'id': 1, 'name': 'new_name'},
+            {'id': 2, 'name': 'new_name'},
+            {'id': 3, 'name': 'new_name'},
+        ]
+
+        mock_response = Mock()
+        type(mock_response).data = PropertyMock(return_value=test_response)
+
+        mock_supabase_query.update.return_value.in_.return_value.execute.return_value = mock_response
+
+        # Execution
+        result = supabase_client.bulk_update(ids=test_ids, data=test_data)
+
+        # Testing
+        mock_supabase_query.update.assert_called_once_with(test_data)
+        mock_supabase_query.update.return_value.in_.assert_called_once_with('id', test_ids)
+
+        assert result == test_response
diff --git a/supadantic/base.py b/supadantic/base.py
index 7f5c4eb..d24fef4 100644
--- a/supadantic/base.py
+++ b/supadantic/base.py
@@ -67,3 +67,8 @@ class BaseDBEntity(BaseModel, ABC):
     def bulk_update(cls, *, ids: List[int], data: dict) -> None:
         db_client = cls._get_db_client()
         db_client.bulk_update(ids=ids, data=data)
+
+    def delete(self: Self) -> None:
+        if self.id:
+            db_client = self._get_db_client()
+            db_client.delete(id=self.id)
diff --git a/supadantic/supabase_client.py b/supadantic/supabase_client.py
index f29c1a3..f365d35 100644
--- a/supadantic/supabase_client.py
+++ b/supadantic/supabase_client.py
@@ -36,3 +36,6 @@ class SupabaseClient:
     def bulk_update(self, *, ids: List[int], data: Dict[str, Any]) -> List[Dict[str, Any]]:
         response = self.query.update(data).in_('id', ids).execute()
         return response.data
+
+    def delete(self, *, id: int) -> None:
+        self.query.delete().eq('id', id).execute()


Test patch:
diff --git a/tests/test_base.py b/tests/test_base.py
index 380f851..c34a95a 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -175,3 +175,23 @@ class TestBaseDBEntity:
             # Testing
             mock_get_db_client.assert_called_once()
             mock_db_client_bulk_update.assert_called_once_with(ids=test_ids, data=test_data)
+
+        def test_delete(
+            self,
+            entity: Type[BaseDBEntity],
+            test_supabase_client: MagicMock,
+            mock_get_db_client: MagicMock,
+            mocker: MockerFixture,
+        ):
+            # Prepare data
+            test_entity_with_id = entity(id=1)
+            test_entity_without_id = entity()
+            mock_db_client_delete = mocker.patch.object(test_supabase_client, 'delete')
+
+            # Execution
+            test_entity_with_id.delete()
+            test_entity_without_id.delete()
+
+            # Testing
+            mock_get_db_client.assert_called_once()
+            mock_db_client_delete.assert_called_once_with(id=1)
diff --git a/tests/test_supabase_client.py b/tests/test_supabase_client.py
index c619148..08ecce4 100644
--- a/tests/test_supabase_client.py
+++ b/tests/test_supabase_client.py
@@ -110,3 +110,16 @@ class TestSupabaseClient:
         mock_supabase_query.update.return_value.in_.assert_called_once_with('id', test_ids)
 
         assert result == test_response
+
+    def test_delete(self, supabase_client: SupabaseClient):
+        # Prepare_data
+        mock_supabase_query = Mock()
+        supabase_client.query = mock_supabase_query
+
+        # Execution
+        supabase_client.delete(id=1)
+
+        # Testing
+        mock_supabase_query.delete.assert_called_once()
+        mock_supabase_query.delete.return_value.eq.assert_called_once_with('id', 1)
+        mock_supabase_query.delete.return_value.eq.return_value.execute.assert_called_once()