How to call javascript in a node.js module from clojurescript? - node.js

I'm hoping to use the Coinbase Bitcoin Exchange node.js API from inside ClojureScript.
The goal is to replicate the first javascript example on the page:
var CoinbaseExchange = require('coinbase-exchange');
var publicClient = new CoinbaseExchange.PublicClient();
But in my following code I've started by trying to access PublicClient at all:
(ns plutus.core
(:require
[cljs.nodejs :as nodejs]))
(def coinb (nodejs/require "coinbase-exchange"))
(nodejs/enable-util-print!)
(defn -main [& args]
(def pc (js/PublicClient.)))
(println pc))
(set! *main-cli-fn* -main)
This throws a ReferenceError: PublicClient is not defined, though I've also tried (along with similar variations):
(def pc (. coinb (PublicClient)))
(def pc (.PublicClient coinb))
(def pc (:PublicClient coinb))
All of which have failed by printing nil. I've pretty closely studied this article for any relevant examples, but I'm confused on how using node.js affects the naming of things, if at all.

Really its not a naming issue, its more about how to use new with nested properties in an object. Unfortunately, you can't get a reference to PublicClient and then new that after the fact.
(new (.-PublicClient coinb))
It does not work even though (.-PublicClient coinb) returns a function.
You need to point to the location of the function, by using it's dot notation within ClojureScript:
(new coinb.PublicClient)
;; OR, more idiomatic
(coinb.PublicClient.)
That should give you what you want.

Anybody else seeing this?
> ((.-getProducts (cb.PublicClient.)) (fn [_ _ _] nil))
#object[TypeError TypeError: self.makeRelativeURI is not a function]

Related

Lookup parameter arrays from URL Queries in Yesod

I am fairly new to Haskell and Yesod so I've been looking through many tutorials and documentation. I found another StackOverflow about parsing url queries: Lookup query parameters in Yesod
That said, the solution there is not working for arrays of parameters in these url queries.
For example:
http://localhost:3000/models/product?field[]=test1&field[]=test2&field[]=test3&domain[]=["id","name",True]&limit=25
As far as I can tell, the /models/product can be handled by defining a route, and I am able to even get the domain[] parameter. However if I do a lookup on field[] I can only get the first value test1 and I have no way to get the rest. Additionally, assuming that I have no foreknowledge of the size of this array, how would I accomplish this?
Thanks!
I solved this via some hack code, but I'm sure there's probably a better solution out there. Just posting this for other's reference:
getProductR :: Handler Value
getProductR = do
getParameters <- reqGetParams <$> getRequest
let fields = [ b | (a,b) <- getParameters , a == "field[]"]
let domains = cleanseInput getParameters "domain[]"
let limit = Import.lookup (Import.pack "limit") getParameters
return $ object [
(Import.pack "fields") .= fields,
(Import.pack "domains") .= domains,
(Import.pack "limit") .= limit
]
cleanseInput params key = [ Data.List.filter (/= "") [Data.Text.filter (/= ',' ) x | x<-(Data.Text.splitOn "\"" (Data.Text.tail (Data.Text.init b)))] | (a,b) <- params , a == key]
To my knowledge, there isn't an HTTP standard way of handling arrays in query parameters. Several tools, like Ruby on Rails or PHP, have their own conventions for expressing arrays in query parameters.
Yesod doesn't have its own format for arrays (or dictionaries, or other data structures) in query parameters, so I don't think there's any official API to handle this.
If you can, I would recommend doing a POST request with a JSON body for this case. If it must be a GET request, you could also do a GET with JSON in the query parameters and parse that. This allows you to avoid writing custom parser code, leverages the power of existing aeson instances, will be more portable across HTTP clients like Android/iOS/the web. This advice is fairly non-standard, admittedly, but it's worked great for me in practice.

when mockito when thenReturn on spy not working?

from the doc: Important gotcha on spying real objects!
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
so, when does when thenReturn not working on spy?
same question here

What are restas render-objects?

When i try to compile the render-object method shown here in the documentation http://restas.lisper.ru/en/manual/special-pages.html,
(defmethod restas:render-object ((designer mydrawer)
(code (eql hunchentoot:+http-internal-server-error+)))
(setf (hunchentoot:content-type*) "text/plain")
"Oh, all very bad")
it gives
There is no class named RESTAURANT::MYDRAWER SIMPLE-ERROR
How do these render-object thingies work ?
render-object is a generic function that takes a rendering object, which is either the object passed to :render-method for define-route or the value of *default-render-method*, and the object to render. It then renders that object (usually as text, although you could probably render it to an octet array as well).
The example assumes that you have a class called mydrawer. To get this working you would need to do something like the following:
(defclass mydrawer () ())
(defmethod restas:render-object ((designer mydrawer)
(code (eql hunchentoot:+http-internal-server-error+)))
(setf (hunchentoot:content-type*) "text/plain")
"Oh, all very bad")
(defmethod restas:render-object ((designer mydrawer) obj)
;; Default rendering of objects goes here,
;; this will just call the default render method
(restas:render-object nil obj))
And then use an instance of mydrawer as the render method either for individual routes, or for a restas module.

How to define function in gremlin that returns the same result as in gremlin shell?

I'm currently using TinkerPop Gremlin (with a Titan backend) to implement a "similar document" algorithm.
The next lines are working perfectly well in gremlin shell :
v = g.v(880068)
m=[:]
v.as('x').out('auto_tag').in('auto_tag').has('status', 1).except('x').groupCount(m).filter{false}
results=[]
m.sort{-it.value}[0..9].each(){key, value -> results.add(key.document_id) }
results
following results are visible :
==>3188749
==>3190640
==>3191407
==>3187753
==>3186634
==>3185534
==>3189883
==>3190108
==>3187088
==>3188890
But when I try to "wrap" the same code in a function, it doesn't work anymore :
v = g.v(880068)
def get_similar_documents(v) {
m=[:]
v.as('x').out('auto_tag').in('auto_tag').has('status', 1).except('x').groupCount(m).filter{false}
results=[]
m.sort{-it.value}[0..9].each(){key, value -> results.add(key.document_id) }
return results
}
get_similar_documents(v)
...nothing is returned
Coming from a Python backend, I assume this is related to variable scope but so far I don't understand how to fix it.
Thanks in advance for any help
Edit : I'm using Bulbs, that's why I'd like to wrap my code in a function (That I could later call from Python)
I think you need to iterate your pipeline when within the get_similar_documents function. Meaning:
v.as('x').out('auto_tag').in('auto_tag').has('status', 1).except('x').groupCount(m).filter{false}.iterate()
It's important to remember that the Gremlin Shell automatically iterates pipelines for you. The shell isn't iterating it within the function so no side-effects are being generated to your m in the groupCount.
You can read more about there here.

Can I redefine String#length?

I'd like to re-implement a method of a Java class. For example, for "hi".length() to return 4. (How) Can I do that?
I know using SomeClass.metaClass I can get a reference to an existing method and define new (or overriding) method, but I can't seem to be able to do that for existing Java methods.
Using Groovy, you can replace any method (even those of final classes) with your own implementation. Method replacement in Groovy uses the meta-object protocol, not inheritance.
Here's the example you requested, i.e. how to make String.length() always return 4
// Redefine the method
String.metaClass.invokeMethod = { name, args ->
def metaMethod = delegate.metaClass.getMetaMethod(name, args)
def result = metaMethod.invoke(delegate, args)
name == 'length' ? 4 : result
}
// Test it
assert "i_do_not_have_4_chars".length() == 4
Seems like it could be possible by abusing String metaClass. But the attempt I've done so far in groovy console didn't led to the expected result :
def oldLength = String.metaClass.length
String.metaClass.length = { ->
return oldLength+10;
}
println "hi".length()
outputs the sad 2
I think you could take a look at Proxy MetaClass or Delegating metaClass.
If you did redefine it, it would only work in Groovy code. Groovy can't change the way Java code executes.
In Groovy, "hi".length() is roughly equivalent to this Java:
stringMetaClass.invokeMethod("hi","length");
Because Groovy doesn't actually call length directly, metaClass tricks work in Groovy code. But Java doesn't know about MetaClasses, so there is no way to make this work.
Although this question is very old I like to point out another way (at least for newer Groovy versions) .
The length() method in java.lang.String is implemented from java.lang.CharSequence interface. In order to reimplement the method using the String-metaClass you need to "override" the method in the metaClass of the interface first.
CharSequence.metaClass.length = { -> -1}
String.metaClass.length = { -> 4 }
assert "i_do_not_have_4_chars".length() == 4
The solution using String.metaClass.invokeMethod changes the behaviour of all String-methods and is problematic. For instance, simply invoking "asdf".size() leads to an exception on my setup.

Resources