packages feed

lackey 1.0.16 → 2.0.0.0

raw patch · 7 files changed

+479/−340 lines, 7 filesdep ~basedep ~servantdep ~servant-foreignPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, servant, servant-foreign, text

API changes (from Hackage documentation)

Files

+ CHANGELOG.markdown view
@@ -0,0 +1,4 @@+# Change log++Lackey follows the [Package Versioning Policy](https://pvp.haskell.org).+You can find release notes [on GitHub](https://github.com/tfausak/lackey/releases).
LICENSE.markdown view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Taylor Fausak+Copyright (c) 2022 Taylor Fausak  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
lackey.cabal view
@@ -1,7 +1,7 @@-cabal-version: >= 1.10+cabal-version: 2.2  name: lackey-version: 1.0.16+version: 2.0.0.0  synopsis: Generate Ruby clients from Servant APIs. description: Lackey generates Ruby clients from Servant APIs.@@ -9,7 +9,7 @@ bug-reports: https://github.com/tfausak/lackey/issues build-type: Simple category: Web-extra-source-files: README.markdown+extra-source-files: CHANGELOG.markdown README.markdown homepage: https://github.com/tfausak/lackey#readme license-file: LICENSE.markdown license: MIT@@ -19,35 +19,57 @@   location: https://github.com/tfausak/lackey   type: git -library+flag pedantic+  default: False+  description: Enables @-Werror@, which turns warnings into errors.+  manual: True++common library   build-depends:-    base >= 4.13.0 && < 4.16-    , servant >= 0.16.2 && < 0.19+    , base >= 4.13.0 && < 4.17     , servant-foreign >= 0.15 && < 0.16     , text >= 1.2.4 && < 1.3   default-language: Haskell2010-  exposed-modules: Lackey   ghc-options:     -Weverything+    -Wno-all-missed-specialisations     -Wno-implicit-prelude     -Wno-missing-exported-signatures     -Wno-unsafe-  hs-source-dirs: src/lib +  if flag(pedantic)+    ghc-options: -Werror+   if impl(ghc >= 8.10)     ghc-options:       -Wno-missing-safe-haskell-mode       -Wno-prepositive-qualified-module +  if impl(ghc >= 9.2)+    ghc-options:+      -Wno-missing-kind-signatures++common executable+  import: library++  build-depends: lackey+  ghc-options:+    -rtsopts+    -threaded+    -Wno-unused-packages++library+  import: library++  exposed-modules: Lackey+  hs-source-dirs: source/library+ test-suite test+  import: executable+   build-depends:-    base -any     , hspec >= 2.7.6 && < 2.10-    , lackey -any-    , servant -any-    , servant-foreign -any-    , text -any-  default-language: Haskell2010-  hs-source-dirs: src/test+    , servant >= 0.16.2 && < 0.19+  hs-source-dirs: source/test-suite   main-is: Main.hs   type: exitcode-stdio-1.0
+ source/library/Lackey.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}++module Lackey+  ( rubyForAPI+  ) where++import qualified Data.Char as Char+import Data.Function ((&))+import qualified Data.Maybe as Maybe+import qualified Data.Proxy as Proxy+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Servant.Foreign as Servant++type Language = Servant.NoTypes++languageProxy :: Proxy.Proxy Language+languageProxy = Proxy.Proxy++type Request = Servant.NoContent++requestProxy :: Proxy.Proxy Request+requestProxy = Proxy.Proxy++renderRequests :: [Servant.Req Request] -> Text.Text+renderRequests requests = requests & fmap renderRequest & Text.intercalate ";"++functionName :: Servant.Req Request -> Text.Text+functionName request = request & Servant._reqFuncName & Servant.snakeCase++hasBody :: Servant.Req Request -> Bool+hasBody request = case Servant._reqBody request of+  Nothing -> False+  Just _ -> True++bodyArgument :: Text.Text+bodyArgument = "body"++underscore :: Text.Text -> Text.Text+underscore text =+  text & Text.toLower & Text.map (\c -> if Char.isAlphaNum c then c else '_')++getHeaders :: Servant.Req Request -> [Text.Text]+getHeaders request =+  request+    & Servant._reqHeaders+    & Maybe.mapMaybe+        (\h -> case h of+          Servant.HeaderArg x -> Just x+          Servant.ReplaceHeaderArg _ _ -> Nothing+        )+    & fmap (Servant.unPathSegment . Servant._argName)++getURLPieces :: Servant.Req Request -> [Either Text.Text Text.Text]+getURLPieces request =+  let+    url = request & Servant._reqUrl+    path =+      url+        & Servant._path+        & Maybe.mapMaybe+            ((\segment -> case segment of+               Servant.Static _ -> Nothing+               Servant.Cap arg -> Just arg+             )+            . Servant.unSegment+            )+        & fmap (Servant.unPathSegment . Servant._argName)+    query = url & Servant._queryStr & fmap+      (Servant.unPathSegment . Servant._argName . Servant._queryArgName)+  in fmap Left path <> fmap Right query++functionArguments :: Servant.Req Request -> Text.Text+functionArguments request = Text.concat+  [ "("+  , [ [Just "excon"]+    , request & getURLPieces & fmap+      (\piece -> Just $ case piece of+        Left capture -> underscore capture+        Right param -> underscore param <> ": nil"+      )+    , request & getHeaders & fmap (Just . (<> ": nil") . underscore)+    , [if hasBody request then Just bodyArgument else Nothing]+    ]+  & concat+  & Maybe.catMaybes+  & Text.intercalate ","+  , ")"+  ]++requestMethod :: Servant.Req Request -> Text.Text+requestMethod request =+  request & Servant._reqMethod & Text.decodeUtf8 & Text.toLower & Text.cons ':'++requestPath :: Servant.Req Request -> Text.Text+requestPath request =+  let+    path =+      request+        & Servant._reqUrl+        & Servant._path+        & fmap+            ((\x -> case x of+               Servant.Static y -> Servant.unPathSegment y+               Servant.Cap y ->+                 let+                   z =+                     y & Servant._argName & Servant.unPathSegment & underscore+                 in "#{" <> z <> "}"+             )+            . Servant.unSegment+            )+        & Text.intercalate "/"+    query =+      request+        & Servant._reqUrl+        & Servant._queryStr+        & fmap+            ((\x -> x <> "=#{" <> underscore x <> "}")+            . Servant.unPathSegment+            . Servant._argName+            . Servant._queryArgName+            )+        & Text.intercalate "&"+    url = "/" <> path <> (if Text.null query then "" else "?" <> query)+  in "\"" <> url <> "\""++requestHeaders :: Servant.Req Request -> Text.Text+requestHeaders request =+  [ ["{"]+    , request & getHeaders & fmap (\x -> "\"" <> x <> "\"=>" <> underscore x)+    , ["}"]+    ]+    & concat+    & Text.concat++requestBody :: Servant.Req Request -> Text.Text+requestBody request = if hasBody request then bodyArgument else "nil"++functionBody :: Servant.Req Request -> Text.Text+functionBody request = Text.concat+  [ "excon.request("+  , ":method=>"+  , requestMethod request+  , ","+  , ":path=>"+  , requestPath request+  , ","+  , ":headers=>"+  , requestHeaders request+  , ","+  , ":body=>"+  , requestBody request+  , ")"+  ]++renderRequest :: Servant.Req Request -> Text.Text+renderRequest request = Text.concat+  [ "def "+  , functionName request+  , functionArguments request+  , functionBody request+  , "end"+  ]++requestsForAPI+  :: ( Servant.HasForeign Language Request api+     , Servant.GenerateList Request (Servant.Foreign Request api)+     )+  => Proxy.Proxy api+  -> [Servant.Req Request]+requestsForAPI api = api & Servant.listFromAPI languageProxy requestProxy++rubyForAPI+  :: ( Servant.HasForeign Language Request api+     , Servant.GenerateList Request (Servant.Foreign Request api)+     )+  => Proxy.Proxy api+  -> Text.Text+rubyForAPI api = api & requestsForAPI & renderRequests
+ source/test-suite/Main.hs view
@@ -0,0 +1,256 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}++import qualified Data.Proxy as Proxy+import qualified Data.Text as Text+import qualified Lackey+import qualified Servant.API as Servant+import qualified Test.Hspec as Hspec++main :: IO ()+main =+  Hspec.hspec+    . Hspec.parallel+    . Hspec.describe "Lackey"+    . Hspec.describe "rubyForAPI"+    $ do++        Hspec.it "supports delete requests" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy (Servant.Delete '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "delete" "" "delete" "" "" False++        Hspec.it "supports get requests" $ do+          let+            api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" "" "get" "" "" False++        Hspec.it "supports patch requests" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy (Servant.Patch '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "patch" "" "patch" "" "" False++        Hspec.it "supports post requests" $ do+          let+            api = Proxy.Proxy :: Proxy.Proxy (Servant.Post '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "post" "" "post" "" "" False++        Hspec.it "supports put requests" $ do+          let+            api = Proxy.Proxy :: Proxy.Proxy (Servant.Put '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "put" "" "put" "" "" False++        Hspec.it "supports alternatives" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Get '[Servant.JSON] () Servant.:<|> Servant.Delete '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api `Hspec.shouldBe` Text.concat+            [ ruby "get" "" "get" "" "" False+            , Text.singleton ';'+            , ruby "delete" "" "delete" "" "" False+            ]++        Hspec.it "supports captures" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Capture "id" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get_by_id" ",id" "get" "#{id}" "" False++        Hspec.it "supports query flags" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryFlag "flag" Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get"+                               ",flag: nil"+                               "get"+                               "?flag=#{flag}"+                               ""+                               False++        Hspec.it "supports query params" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryParam "param" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get"+                               ",param: nil"+                               "get"+                               "?param=#{param}"+                               ""+                               False++        Hspec.it "supports multiple query params" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryParams "params" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get"+                               ",params: nil"+                               "get"+                               "?params=#{params}"+                               ""+                               False++        Hspec.it "supports request bodies" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" ",body" "get" "" "" True++        Hspec.it "supports request headers" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Header "cookie" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get"+                               ",cookie: nil"+                               "get"+                               ""+                               "\"cookie\"=>cookie"+                               False++        Hspec.it "supports response headers" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  (Servant.Get '[Servant.JSON] (Servant.Headers '[] ()))+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" "" "get" "" "" False++        Hspec.it "puts the body param after captures" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Capture "segment" () Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get_by_segment"+                               ",segment,body"+                               "get"+                               "#{segment}"+                               ""+                               True++        Hspec.it "puts the body param after query params" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryFlag "flag" Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby+                               "get"+                               ",flag: nil,body"+                               "get"+                               "?flag=#{flag}"+                               ""+                               True++        Hspec.it "sanitizes path segments" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ("A!" Servant.:> Servant.Get '[Servant.JSON] ())+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get_A!" "" "get" "A!" "" False++        Hspec.it "sanitizes captures" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Capture "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get_by_A!" ",a_" "get" "#{a_}" "" False++        Hspec.it "sanitizes query flags" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryFlag "A!" Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++        Hspec.it "sanitizes query params" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryParam "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++        Hspec.it "sanitizes multiple query params" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.QueryParams "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++        Hspec.it "sanitizes headers" $ do+          let+            api =+              Proxy.Proxy :: Proxy.Proxy+                  ( Servant.Header "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+                  )+          Lackey.rubyForAPI api+            `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "" "\"A!\"=>a_" False++-- Since every generated function has the same structure, it can be abstracted+-- away behind this function.+ruby :: String -> String -> String -> String -> String -> Bool -> Text.Text+ruby name params method path headers body = Text.pack+  (concat+    [ "def "+    , name+    , "(excon"+    , params+    , ")"+    , "excon.request("+    , ":method=>:"+    , method+    , ","+    , ":path=>\"/"+    , path+    , "\","+    , ":headers=>{"+    , headers+    , "},"+    , ":body=>"+    , if body then "body" else "nil"+    , ")"+    , "end"+    ]+  )
− src/lib/Lackey.hs
@@ -1,191 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}--module Lackey-  ( rubyForAPI-  ) where--import qualified Data.Char as Char-import Data.Function ((&))-import qualified Data.Maybe as Maybe-import qualified Data.Proxy as Proxy-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Servant.Foreign as Servant--type Language = Servant.NoTypes--languageProxy :: Proxy.Proxy Language-languageProxy = Proxy.Proxy--type Request = Servant.NoContent--requestProxy :: Proxy.Proxy Request-requestProxy = Proxy.Proxy--renderRequests :: [Servant.Req Request] -> Text.Text-renderRequests requests = requests & map renderRequest & Text.intercalate ";"--functionName :: Servant.Req Request -> Text.Text-functionName request = request & Servant._reqFuncName & Servant.snakeCase--hasBody :: Servant.Req Request -> Bool-hasBody request =-  case Servant._reqBody request of-    Nothing -> False-    Just _ -> True--bodyArgument :: Text.Text-bodyArgument = "body"--underscore :: Text.Text -> Text.Text-underscore text =-  text & Text.toLower &-  Text.map-    (\c ->-       if Char.isAlphaNum c-         then c-         else '_')--getHeaders :: Servant.Req Request -> [Text.Text]-getHeaders request =-  request & Servant._reqHeaders &-  Maybe.mapMaybe-    (\h ->-       case h of-         Servant.HeaderArg x -> Just x-         Servant.ReplaceHeaderArg _ _ -> Nothing) &-  map Servant._argName &-  map Servant.unPathSegment--getURLPieces :: Servant.Req Request -> [Either Text.Text Text.Text]-getURLPieces request =-  let url = request & Servant._reqUrl-      path =-        url & Servant._path & map Servant.unSegment &-        Maybe.mapMaybe-          (\segment ->-             case segment of-               Servant.Static _ -> Nothing-               Servant.Cap arg -> Just arg) &-        map Servant._argName &-        map Servant.unPathSegment-      query =-        url & Servant._queryStr & map Servant._queryArgName &-        map Servant._argName &-        map Servant.unPathSegment-  in map Left path ++ map Right query--functionArguments :: Servant.Req Request -> Text.Text-functionArguments request =-  Text.concat-    [ "("-    , [ [Just "excon"]-      , request & getURLPieces &-        map-          (\piece ->-             case piece of-               Left capture -> underscore capture-               Right param -> underscore param <> ": nil") &-        map Just-      , request & getHeaders & map underscore & map (<> ": nil") & map Just-      , [ if hasBody request-            then Just bodyArgument-            else Nothing-        ]-      ] &-      concat &-      Maybe.catMaybes &-      Text.intercalate ","-    , ")"-    ]--requestMethod :: Servant.Req Request -> Text.Text-requestMethod request =-  request & Servant._reqMethod & Text.decodeUtf8 & Text.toLower & Text.cons ':'--requestPath :: Servant.Req Request -> Text.Text-requestPath request =-  let path =-        request & Servant._reqUrl & Servant._path & map Servant.unSegment &-        map-          (\x ->-             case x of-               Servant.Static y -> Servant.unPathSegment y-               Servant.Cap y ->-                 let z =-                       y & Servant._argName & Servant.unPathSegment & underscore-                 in "#{" <> z <> "}") &-        Text.intercalate "/"-      query =-        request & Servant._reqUrl & Servant._queryStr &-        map Servant._queryArgName &-        map Servant._argName &-        map Servant.unPathSegment &-        map (\x -> x <> "=#{" <> underscore x <> "}") &-        Text.intercalate "&"-      url =-        "/" <> path <>-        (if Text.null query-           then ""-           else "?" <> query)-  in "\"" <> url <> "\""--requestHeaders :: Servant.Req Request -> Text.Text-requestHeaders request =-  [ ["{"]-  , request & getHeaders & map (\x -> "\"" <> x <> "\"=>" <> underscore x)-  , ["}"]-  ] &-  concat &-  Text.concat--requestBody :: Servant.Req Request -> Text.Text-requestBody request =-  if hasBody request-    then bodyArgument-    else "nil"--functionBody :: Servant.Req Request -> Text.Text-functionBody request =-  Text.concat-    [ "excon.request("-    , ":method=>"-    , requestMethod request-    , ","-    , ":path=>"-    , requestPath request-    , ","-    , ":headers=>"-    , requestHeaders request-    , ","-    , ":body=>"-    , requestBody request-    , ")"-    ]--renderRequest :: Servant.Req Request -> Text.Text-renderRequest request =-  Text.concat-    [ "def "-    , functionName request-    , functionArguments request-    , functionBody request-    , "end"-    ]--requestsForAPI ::-     ( Servant.HasForeign Language Request api-     , Servant.GenerateList Request (Servant.Foreign Request api)-     )-  => Proxy.Proxy api-  -> [Servant.Req Request]-requestsForAPI api = api & Servant.listFromAPI languageProxy requestProxy--rubyForAPI ::-     ( Servant.HasForeign Language Request api-     , Servant.GenerateList Request (Servant.Foreign Request api)-     )-  => Proxy.Proxy api-  -> Text.Text-rubyForAPI api = api & requestsForAPI & renderRequests
− src/test/Main.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}--import qualified Data.Proxy as Proxy-import qualified Data.Text as Text-import qualified Lackey-import qualified Servant.API as Servant-import qualified Test.Hspec as Hspec--main :: IO ()-main = Hspec.hspec . Hspec.parallel . Hspec.describe "Lackey" . Hspec.describe "rubyForAPI" $ do--  Hspec.it "supports delete requests" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Delete '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "delete" "" "delete" "" "" False--  Hspec.it "supports get requests" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" "" "get" "" "" False--  Hspec.it "supports patch requests" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Patch '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "patch" "" "patch" "" "" False--  Hspec.it "supports post requests" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Post '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "post" "" "post" "" "" False--  Hspec.it "supports put requests" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Put '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "put" "" "put" "" "" False--  Hspec.it "supports alternatives" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] () Servant.:<|> Servant.Delete '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe` Text.concat-      [ ruby "get" "" "get" "" "" False-      , Text.singleton ';'-      , ruby "delete" "" "delete" "" "" False-      ]--  Hspec.it "supports captures" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "id" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get_by_id" ",id" "get" "#{id}" "" False--  Hspec.it "supports query flags" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "flag" Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",flag: nil" "get" "?flag=#{flag}" "" False--  Hspec.it "supports query params" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParam "param" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",param: nil" "get" "?param=#{param}" "" False--  Hspec.it "supports multiple query params" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParams "params" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",params: nil" "get" "?params=#{params}" "" False--  Hspec.it "supports request bodies" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",body" "get" "" "" True--  Hspec.it "supports request headers" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Header "cookie" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",cookie: nil" "get" "" "\"cookie\"=>cookie" False--  Hspec.it "supports response headers" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] (Servant.Headers '[] ()))-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" "" "get" "" "" False--  Hspec.it "puts the body param after captures" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "segment" () Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get_by_segment" ",segment,body" "get" "#{segment}" "" True--  Hspec.it "puts the body param after query params" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "flag" Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",flag: nil,body" "get" "?flag=#{flag}" "" True--  Hspec.it "sanitizes path segments" $ do-    let api = Proxy.Proxy :: Proxy.Proxy ("A!" Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get_A!" "" "get" "A!" "" False--  Hspec.it "sanitizes captures" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "A!" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get_by_A!" ",a_" "get" "#{a_}" "" False--  Hspec.it "sanitizes query flags" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "A!" Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False--  Hspec.it "sanitizes query params" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParam "A!" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False--  Hspec.it "sanitizes multiple query params" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParams "A!" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False--  Hspec.it "sanitizes headers" $ do-    let api = Proxy.Proxy :: Proxy.Proxy (Servant.Header "A!" () Servant.:> Servant.Get '[Servant.JSON] ())-    Lackey.rubyForAPI api `Hspec.shouldBe`-      ruby "get" ",a_: nil" "get" "" "\"A!\"=>a_" False---- Since every generated function has the same structure, it can be abstracted--- away behind this function.-ruby :: String -> String -> String -> String -> String -> Bool -> Text.Text-ruby name params method path headers body = Text.pack (concat-  [ "def ", name, "(excon", params, ")"-  , "excon.request("-  , ":method=>:", method, ","-  , ":path=>\"/", path, "\","-  , ":headers=>{", headers, "},"-  , ":body=>", if body then "body" else "nil"-  , ")"-  , "end"-  ])