Ver código fonte

Improve factory relation generation

shalvah 4 anos atrás
pai
commit
6a61de0cf7

+ 14 - 12
CHANGELOG.md

@@ -13,22 +13,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 ### Removals
 
 ## 
-- Change Strategy class method signature
-- Rename 'value' in parameters to 'example'
+- Infer URL parameter type and name
+- Support headers in response
+- Include responses in Postman collection
+- Body parameters array
+- More validation rules support
+- Inline validators
+- 3 base URLs
+- static docs fix
+  
 - `include` not supported in frontmatter; use prepend or append
 - Endpoints in views are now objects
 - moved body-parameters to components
 - index renamed to intro.blade.php
 - views moved to markdown/
-- Removed continue_without_database_transactions
-- Support headers in response
-- Include responses in Postman collection
-- Body parameters array
-- Auto detect Dingo
+- Remove `prepend.md`
+- Remove md files for YAML
+
 - Removed `$stage`
-- More validation rules support
-- Inline validators
-- Infer URL parameter type and name
+- Auto detect Dingo
 - Renamed `interactive` to `try_it_out`
-- 3 base URLs
-- Remove `prepend.md`
+- Removed continue_without_database_transactions

+ 9 - 12
config/scribe.php

@@ -247,7 +247,7 @@ INTRO
     /*
      * Example requests for each endpoint will be shown in each of these languages.
      * Supported options are: bash, javascript, php, python
-     * To add a language of your own, see https://scribe.readthedocs.io/en/latest/customization.html
+     * To add a language of your own, see https://scribe.knuckles.wtf/laravel/advanced/adding-example-languages
      *
      */
     'example_languages' => [
@@ -290,14 +290,13 @@ INTRO
     ],
 
     /*
-     * Name for the group of endpoints which do not have a @group set.
+     * Endpoints which don't have a @group will be placed in this default group.
      */
     'default_group' => 'Endpoints',
 
     /*
      * Custom logo path. This will be used as the value of the src attribute for the <img> tag,
-     * so make sure it points to a public URL or path accessible from your web server. For best results, the image width should be 230px.
-     * Set this to false to not use a logo.
+     * so make sure it points to an accessible URL or path. Set to false to not use a logo.
      *
      * For example, if your logo is in public/img:
      * - 'logo' => '../img/logo.png' // for `static` type (output folder is public/docs)
@@ -314,7 +313,7 @@ INTRO
 
     /**
      * The strategies Scribe will use to extract information about your routes at each stage.
-     * If you write or install a custom strategy, add it here.
+     * If you create or install a custom strategy, add it here.
      */
     'strategies' => [
         'metadata' => [
@@ -349,9 +348,6 @@ INTRO
         ],
     ],
 
-    /*
-     * Configure how responses are transformed using @transformer and @transformerCollection (requires league/fractal package)
-     */
     'fractal' => [
         /* If you are using a custom serializer with league/fractal, you can specify it here.
          * Leave as null to use no serializer or return simple JSON.
@@ -360,15 +356,16 @@ INTRO
     ],
 
     /*
-     * [Advanced] If you would like to customize how routes are matched beyond the route configuration you may
-     * declare your own implementation of RouteMatcherInterface
+     * [Advanced] Custom implementation of RouteMatcherInterface to customise how routes are matched
      *
      */
     'routeMatcher' => \Knuckles\Scribe\Matching\RouteMatcher::class,
 
     /**
-     * For response calls, api resource responses and transformer responses, Scribe will try to start database transactions, so no changes are persisted to your database.
-     * Tell Scribe which connections should be transacted here. If you only use the default db connection, you can leave this as is.
+     * For response calls, API resource responses and transformer responses,
+     * Scribe will try to start database transactions, so no changes are persisted to your database.
+     * Tell Scribe which connections should be transacted here.
+     * If you only use one db connection, you can leave this as is.
      */
     'database_connections_to_transact' => [config('database.default')]
 ];

+ 2 - 2
src/Extracting/ParsesValidationRules.php

@@ -282,7 +282,7 @@ trait ParsesValidationRules
                 $parameterData['description'] .= ' ' . $this->getDescription($rule, [':date' => "<code>{$arguments[0]}</code>"]);
                 // TODO introduce the concept of "modifiers", like date_format
                 $startDate = isset($allParameters[$arguments[0]]) ? null : $arguments[0];
-                $parameterData['setter'] = fn() => $this->getFaker()->dateTimeBetween($startDate)->format('Y-m-d');
+                $parameterData['setter'] = fn() => $this->getFaker()->dateTimeBetween($startDate, '+100 years')->format('Y-m-d');
                 break;
             case 'before':
             case 'before_or_equal':
@@ -290,7 +290,7 @@ trait ParsesValidationRules
                 // The argument can be either another field or a date
                 $endDate = isset($allParameters[$arguments[0]]) ? null : $arguments[0];
                 $parameterData['description'] .= ' ' . $this->getDescription($rule, [':date' => "<code>{$arguments[0]}</code>"]);
-                $parameterData['setter'] = fn() => $this->getFaker()->dateTimeBetween(null, $endDate)->format('Y-m-d');
+                $parameterData['setter'] = fn() => $this->getFaker()->dateTimeBetween('-30 years', $endDate)->format('Y-m-d');
                 break;
             case 'starts_with':
                 $parameterData['description'] .= ' The value must start with one of ' . w::getListOfValuesAsFriendlyHtmlString($arguments);

+ 4 - 10
src/Extracting/Strategies/Responses/UseApiResourceTags.php

@@ -2,6 +2,7 @@
 
 namespace Knuckles\Scribe\Extracting\Strategies\Responses;
 
+use Illuminate\Support\Str;
 use Knuckles\Camel\Extraction\ExtractedEndpointData;
 use Exception;
 use Illuminate\Database\Eloquent\Model;
@@ -182,19 +183,12 @@ class UseApiResourceTags extends Strategy
     {
         try {
             // Try Eloquent model factory
+            $factory = Utils::getModelFactory($type, $factoryStates, $relations);
 
-            // Factories are usually defined without the leading \ in the class name,
-            // but the user might write it that way in a comment. Let's be safe.
-            $type = ltrim($type, '\\');
-
-            $factory = Utils::getModelFactory($type, $factoryStates);
             try {
-                $model = $factory->create();
-                $model->load($relations);
-
-                return $model;
+                return $factory->create();
             } catch (Exception $e) {
-                // If there was no working database, it would fail.
+                // If there was no working database, ->create() would fail. Try ->make() instead
                 return $factory->make();
             }
         } catch (Exception $e) {

+ 3 - 5
src/Extracting/Strategies/Responses/UseTransformerTags.php

@@ -154,15 +154,13 @@ class UseTransformerTags extends Strategy
         try {
             // try Eloquent model factory
 
-            // Factories are usually defined without the leading \ in the class name,
-            // but the user might write it that way in a comment. Let's be safe.
-            $type = ltrim($type, '\\');
+            /** @var \Illuminate\Database\Eloquent\Factories\Factory $factory */
+            $factory = Utils::getModelFactory($type, $factoryStates, $relations);
 
-            $factory = Utils::getModelFactory($type, $factoryStates);
             try {
                 return $factory->create();
             } catch (Exception $e) {
-                // If there was no working database, it would fail.
+                // If there was no working database, ->create() would fail. Try ->make() instead
                 return $factory->make();
             }
         } catch (Exception $e) {

+ 14 - 5
src/Tools/Utils.php

@@ -178,14 +178,23 @@ class Utils
         return substr($typeName, 0, -2);
     }
 
-    public static function getModelFactory(string $modelName, array $states = [])
+    public static function getModelFactory(string $modelName, array $states = [], array $relations = [])
     {
+        // Factories are usually defined without the leading \ in the class name,
+        // but the user might write it that way in a comment. Let's be safe.
+        $modelName = ltrim($modelName, '\\');
+
         if (method_exists($modelName, 'factory')) { // Laravel 8 type factory
+            /** @var \Illuminate\Database\Eloquent\Factories\Factory $factory */
             $factory = call_user_func_array([$modelName, 'factory'], []);
-            if (count($states)) {
-                foreach ($states as $state) {
-                    $factory = $factory->$state();
-                }
+            foreach ($states as $state) {
+                $factory = $factory->$state();
+            }
+
+            foreach ($relations as $relation) {
+                // Eg "posts" relation becomes hasPosts() method
+                $methodName = "has$relation";
+                $factory = $factory->$methodName();
             }
         } else {
             $factory = factory($modelName);

+ 4 - 1
src/Tools/WritingUtils.php

@@ -181,7 +181,10 @@ class WritingUtils
         }
     }
 
-    public static function getVersionedAsset(string $assetPath)
+    /**
+     * Convert a path like 'js/tryitout.js' to include the current Scribe version ('js/tryitout-3.0.1.js')
+     */
+    public static function getVersionedAsset(string $assetPath): string
     {
         $index = strrpos($assetPath, ".");
         return substr_replace($assetPath, '-'.Globals::SCRIBE_VERSION, $index, 0);