From e8277bddd318b564d89c3c140128c6a72a7b4f32 Mon Sep 17 00:00:00 2001 From: agris <33702214+agrism@users.noreply.github.com> Date: Fri, 3 Nov 2023 08:00:45 +0200 Subject: [PATCH] To prevent the creation of a new record in the database, correct the hash key. (#15) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix hash key creation * fix model static fn insert * Add unit tests to ensure prevention of duplicate records during model updates and for filtering queried results. --------- Co-authored-by: Châu Đình Châu Ái <36218616+alvin0@users.noreply.github.com> --- src/Builder.php | 3 +- src/Model.php | 4 +- tests/ModelTest.php | 104 ++++++++++++++++++++++++++++++++++++++---- tests/Models/User.php | 5 ++ 4 files changed, 104 insertions(+), 12 deletions(-) diff --git a/src/Builder.php b/src/Builder.php index ecd608b..a0cf0d0 100644 --- a/src/Builder.php +++ b/src/Builder.php @@ -360,8 +360,7 @@ public function compileHashByFields(array $attributes) foreach ($listKey as $key) { $attributeValue = $attributes[$key] ?? '*'; - $attributeValue = is_string($attributeValue) ? $attributeValue : json_encode($attributeValue); - $stringKey .= $key . ':' . $attributeValue . ':'; + $stringKey .= $key . ':' . ($attributeValue === '*' ? '*' : $this->model->castAttributeBeforeSave($key, $attributeValue)) . ':'; } return $this->model->getTable() . ":" . rtrim($stringKey, ':'); diff --git a/src/Model.php b/src/Model.php index ed5c3cc..e250467 100644 --- a/src/Model.php +++ b/src/Model.php @@ -535,7 +535,7 @@ protected function performUpdate(Builder $build) * * @return mixed The */ - protected function castAttributeBeforeSave($key, $value) { + public function castAttributeBeforeSave($key, $value) { // Cast the attribute if necessary $value = $this->hasCast($key) ? $this->castAttribute($key, $value) : $value; @@ -672,7 +672,7 @@ public static function insert(array $dataInsert, Redis $hasTransaction = null) } $inserts[$key] = collect($attributes)->map(function ($item, $key) use ($model) { - return (string) $this->castAttributeBeforeSave($key, $item); + return (string) $model->castAttributeBeforeSave($key, $item); })->toArray(); } else { return false; diff --git a/tests/ModelTest.php b/tests/ModelTest.php index d138cc9..498f1a5 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -9,7 +9,6 @@ it('a user can be created without id', function ($userInput, $expect) { $user = User::create($userInput); - expect($user->name)->toEqual($expect['name']); expect($user->email)->toEqual($expect['email']); })->with([ @@ -28,6 +27,7 @@ ]); it('can insert multiple users without id', function ($data) { + User::insert($data); $users = User::get(); @@ -118,7 +118,7 @@ function () { ], ]); -it('can retrieve all users', function ($setup) { +it('can retrieve all users', function () { expect(User::all()->count())->toBeGreaterThan(0); })->with([ [ @@ -140,10 +140,9 @@ function () { ], ]); -it('can retrieve a single user by ID', function ($createData, $expect) { - $createData(); - +it('can retrieve a single user by ID', function ($expect) { $user = User::find(1); + expect($user->name)->toEqual($expect['name']); expect($user->email)->toEqual($expect['email']); })->with([ @@ -157,9 +156,7 @@ function () { ], ]); -it('can retrieve users matching a given criteria', function ($createData, $expect) { - $createData(); - +it('can retrieve users matching a given criteria', function ($expect) { $users = User::where('name', 'Nuno*')->get(); expect($users->count())->toBeGreaterThan(0); @@ -282,3 +279,94 @@ function () { return $data; } ]); + +it('can retrieve users by email', function () { + $users = User::query()->where('email', 'nuno_naduro@example.com')->get(); + + expect(2)->toEqual($users->count()); +})->with([ + [ + fn() => User::insert([ + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.com'], + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.com'], + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.net'], + ]), + ], + [ + fn() => User::insert([ + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.net'], + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.com'], + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.com'], + ]), + ] +]); + +it('can create user assigning model property values', function ($userData, $expected) { + $user = User::query()->where('email', 'nuno_naduro@example.com')->first(); + + expect($expected['name'])->toEqual($user->name); + expect($expected['email'])->toEqual($user->email); +})->with([ + [ + function () { + $user = new User; + $user->name = 'Nuno Maduro'; + $user->email = 'nuno_naduro@example.com'; + $user->save(); + }, + ['name' => 'Nuno Maduro', 'email' => 'nuno_naduro@example.com'], + ] +]); + +it('can update user subKey without duplication', function () { + expect(1)->toEqual(User::query()->count()); +})->with([ + [ + function () { + $user = new User; + $user->name = 'Nuno Maduro'; + $user->email = 'nuno_naduro@example.com'; + $user->save(); + $user->email = 'nuno_naduro@example.net'; + $user->save(); + }, + ], + [ + function () { + $user = new User; + $user->name = 'Nuno Maduro'; + $user->email = 'nuno_naduro@example.com'; + $user->save(); + $user->name = 'Nuno'; + $user->email = 'nuno_naduro@example.net'; + $user->save(); + }, + ] +]); + +it('can update user primaryKey without duplication', function () { + expect(1)->toEqual(User::query()->count()); +})->with([ + [ + function () { + $user = new User; + $user->id = '1'; + $user->name = 'Nuno Maduro'; + $user->email = 'nuno_naduro@example.com'; + $user->save(); + $user->id = 2; + $user->save(); + }, + ], + [ + function () { + $user = new User; + $user->id = 1; + $user->name = 'Nuno Maduro'; + $user->email = 'nuno_naduro@example.com'; + $user->save(); + $user->id = 2; + $user->save(); + }, + ] +]); \ No newline at end of file diff --git a/tests/Models/User.php b/tests/Models/User.php index 70a86cf..2be98ab 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -3,6 +3,11 @@ use Alvin0\RedisModel\Model; +/** + * @property $id + * @property $email + * @property $name + */ class User extends Model { /**