Hi, working on PouchDB, I would like to pass the following object:
{
_id: '_design/index',
views: {
index: {
map: function mapFun(doc) {
emit(doc);
}.toString()
}
}
}
My question is simple: what's the best way to create such an object using Fable? More precisely, how do I create a JS function and pass it to the map field?
Thanks!
Probably not the best way, but the fastest if you have many object literals like these and you don't feel like giving everything a type, just use createObj:
open Fable.Core
open Fable.Core.JsInterop
// your emit logic
let emit (x: 'a) = int x
let record =
createObj [
"_id" ==> "_design/index"
"view" ==>
createObj [
"index" ==>
createObj [
"map" ==> unbox (fun doc -> emit doc)
]
]
]
Translates to:
export function emit(x) {
return x | 0;
}
export const record = {
_id: "_design/index",
view: {
index: {
map: function (doc) {
return emit(doc);
}
}
}
};
@whitetigle I am a bit surprise by the named function and the toString() at the end of it.
From our previous conversation, I suspect pouchDb will try to deserialize the "object" into a json representation and re-build it on the other. (it's probably the reason of the named function or toString.
You can find here a live version of the following code. I didn't try to add neither of the name and toString because I am not sure this is intended or no in your code. If you need them, we probably need to explore a bit more Fable capabilities or use macro to generate the right code.
open Fable.Core
open Fable.Core.JsInterop
// Create an jObject manually
let data1 =
createObj [
"_id" ==> "_design/index"
"views" ==>
createObj [
"index" ==>
createObj [
"map" ==> fun doc ->
printfn "%A" doc
]
]
]
// Use an interface
type IRequest =
abstract _id: string with get, set
abstract views: IViews with get, set
and IViews =
abstract index: IIndex with get, set
and IIndex =
abstract map: (obj -> unit) with get, set
let request = createEmpty<IRequest>
let views = createEmpty<IViews>
let index = createEmpty<IIndex>
index.map <- fun doc -> printfn "%A" doc
views.index <- index
request._id <- "_design/index"
request.views <- views
// Use interface with jsOptions
let request2 = jsOptions<IRequest>(fun r ->
r._id <- "_design/index"
r.views <- jsOptions<IViews>(fun v ->
v.index <- jsOptions<IIndex>(fun i ->
i.map <- fun doc -> printfn "%A" doc
)
)
)
// Use keyValueList
[<Pojo>]
type RRequest =
{ _id : string
views : RViews }
and [<Pojo>] RViews =
{ index : RIndex }
and [<Pojo>] RIndex =
{ map: obj -> unit }
let request3 =
{ _id = "_design/index"
views =
{ index =
{ map = fun doc -> printfn "%A" doc } } }
type KRequest =
| [<CompiledName("_id")>] Id of string
static member Views (props: KViews list): KRequest = unbox("views", keyValueList CaseRules.LowerFirst props)
and KViews =
static member Views (props : KIndex list) : KViews = unbox("index", keyValueList CaseRules.LowerFirst props)
and KIndex =
| Map of (obj -> unit)
let requestK =
[ KRequest.Id "_design/index"
KRequest.Views
[ KViews.Views
[ KIndex.Map (fun doc -> printfn "%A" doc )]
]
]
|> keyValueList CaseRules.LowerFirst
Fable.Import.JS.console.log requestK
Thanks guys!
This morning I tried three methods:
createObj Since this kind of object is somehow dynamic (id label must match the field name in the field views) I ended up using createObj.
I feel Interfaces are way to complex just like KeyValueList but then it's because the object structure has nested fields so it's understandable.
Anyway, thanks for your explanations and samples.
I think this information should be added somewhere. Maybe in as an update to your awesome jsInterop tutorial @Zaid-Ajaj?
Closing this :)
Most helpful comment
@whitetigle I am a bit surprise by the named function and the
toString()at the end of it.From our previous conversation, I suspect pouchDb will try to deserialize the "object" into a json representation and re-build it on the other. (it's probably the reason of the named function or
toString.You can find here a live version of the following code. I didn't try to add neither of the name and
toStringbecause I am not sure this is intended or no in your code. If you need them, we probably need to explore a bit more Fable capabilities or usemacroto generate the right code.