Repository: wafflespeanut/paperclip
Pull request #259 (2020-11-10 16:01:13)

api_v2_operation macro adds support for multi word tags
This change adds possibility to add multi word tags via str literal:
```
#[api_v2_operation(tags("Nice cars", Dogs))]
fn some_cats_cars_images() -> impl Future<Output = web::Json<Vec<Image>>>
```


Patch:
diff --git a/book/actix-plugin.md b/book/actix-plugin.md
index 8f7277f6..6552b5cd 100644
--- a/book/actix-plugin.md
+++ b/book/actix-plugin.md
@@ -199,7 +199,7 @@ This can be overridden by explicitly specifying `summary` and `description` in t
   operation_id = "my_handler",
   consumes = "application/yaml, application/json",
   produces = "application/yaml, application/json",
-  tags(Cats, Dogs),
+  tags(Cats, Dogs, "Api reference"),
 )]
 async fn my_handler() -> Json<Foo> { /* */ }
 ```
@@ -316,8 +316,8 @@ spec.tags = vec![
         external_docs: None,
     },
     Tag {
-        name: "Cars".to_string(),
-        description: Some("Images of nice cars".to_string()),
+        name: "Api reference".to_string(),
+        description: Some("List of all api endpoints".to_string()),
         external_docs: None,
     },
 ];
diff --git a/core/src/v2/schema.rs b/core/src/v2/schema.rs
index 6507694b..9388c151 100644
--- a/core/src/v2/schema.rs
+++ b/core/src/v2/schema.rs
@@ -202,6 +202,8 @@ impl_type_simple!(
 );
 #[cfg(feature = "chrono")]
 impl_type_simple!(chrono::NaiveDate, DataType::String, DataTypeFormat::Date);
+#[cfg(feature = "chrono")]
+impl_type_simple!(chrono::NaiveTime, DataType::String);
 #[cfg(feature = "rust_decimal")]
 impl_type_simple!(
     rust_decimal::Decimal,
diff --git a/macros/src/actix.rs b/macros/src/actix.rs
index 382d6692..cd295ebd 100644
--- a/macros/src/actix.rs
+++ b/macros/src/actix.rs
@@ -296,6 +296,8 @@ fn parse_operation_attrs(attrs: TokenStream) -> (Vec<Ident>, Vec<proc_macro2::To
                         for meta in nested.pairs().map(|pair| pair.into_value()) {
                             if let NestedMeta::Meta(Meta::Path(Path { segments, .. })) = meta {
                                 tags.push(segments[0].ident.to_string());
+                            } else if let NestedMeta::Lit(Lit::Str(lit)) = meta {
+                                tags.push(lit.value());
                             } else {
                                 emit_error!(
                                     meta.span(),
diff --git a/src/build/build.rs b/src/build/build.rs
index 833ced5c..ab897da0 100644
--- a/src/build/build.rs
+++ b/src/build/build.rs
@@ -39,7 +39,7 @@ mod template {
         ",
         );
         contents.push_str(&name);
-        contents.push_str(",");
+        contents.push(',');
     }
 
     contents.push_str(


Test patch:
diff --git a/tests/test_app.rs b/tests/test_app.rs
index 72c680f9..68a09332 100644
--- a/tests/test_app.rs
+++ b/tests/test_app.rs
@@ -1314,6 +1314,11 @@ fn test_tags() {
         ready(web::Json(Vec::new()))
     }
 
+    #[api_v2_operation(tags(Cats, "Nice cars"))]
+    fn some_cats_cars_images() -> impl Future<Output = web::Json<Vec<Image>>> {
+        ready(web::Json(Vec::new()))
+    }
+
     run_and_check_app(
         || {
             let mut spec = DefaultApiRaw::default();
@@ -1329,7 +1334,7 @@ fn test_tags() {
                     external_docs: None,
                 },
                 Tag {
-                    name: "Cars".to_string(),
+                    name: "Nice cars".to_string(),
                     description: Some("Images of nice cars".to_string()),
                     external_docs: None,
                 },
@@ -1344,6 +1349,9 @@ fn test_tags() {
                 .wrap_api_with_spec(spec)
                 .with_json_spec_at("/api/spec")
                 .service(web::resource("/images/pets").route(web::get().to(some_pets_images)))
+                .service(
+                    web::resource("/images/cats/cars").route(web::get().to(some_cats_cars_images)),
+                )
                 .build()
         },
         |addr| {
@@ -1393,6 +1401,22 @@ fn test_tags() {
                                 },
                                 "tags":[ "Cats", "Dogs" ]
                             }
+                        },
+                        "/images/cats/cars":{
+                            "get":{
+                                "responses":{
+                                "200":{
+                                    "description":"OK",
+                                    "schema":{
+                                        "items":{
+                                            "$ref":"#/definitions/Image"
+                                        },
+                                        "type":"array"
+                                    }
+                                }
+                                },
+                                "tags":[ "Cats", "Nice cars" ]
+                            }
                         }
                     },
                     "swagger":"2.0",
@@ -1407,7 +1431,7 @@ fn test_tags() {
                         },
                         {
                             "description":"Images of nice cars",
-                            "name":"Cars"
+                            "name":"Nice cars"
                         }
                     ]
                 }),