I have a a graphql query that has a data node that requires all quotation marks to be escaped like so:
data: "{\"access_token\": \"SOME_TOKEN\"}".
However, in the program I am writing, SOME_TOKEN is dynamic and thus I need to use a variable to reference the access token. However, because the token is a string, it has quotation marks as part of the variable. I would usually do something like access_token_var.replace(""", "\") but because this is graphql-client, the entire thing is wrapped in a string.
I am getting the error Variable $access_token is declared by __anonymous__ but not used.
How can I escape the quotes that are included in the string variable?
Full query:
CREATE_AUTHENTICATION_MUTATION ||= <<-'GRAPHQL'
mutation($access_token: String!, $refresh_token: String!, $user_id: ID!, $created_at: Int!, $__created: Int!, $expires_in: Int!){
createUserAuthentication(input: {
name: "my_test",
data: "
{\"access_token\": $access_token, \"refresh_token\": $refresh_token, \"user_id\": $user_id, \"instance_url\": \"REDACTED\", \"created_at\": $created_at, \"__created\": $__created, \"token_type\": \"bearer\", \"expires_in\": $expires_in}"
}){
authenticationId
clientMutationId
}
}
GRAPHQL
Your problem isn't the quotes, it's that data is just a string: no interpolation is taking place and so your resulting value will just be a string literal {"access_token": $access_token, ...}.
GraphQL uses javascript as a backend, so you can probably do something like the following:
...
data: "{\"access_token\": \"" + $access_token + "\", \"refresh_token\": \"" + $refresh_token + "\", \"user_id\": \"" + $user_id + "\", \"instance_url\": \"REDACTED\", \"created_at\": \"" + $created_at + "\", \"__created\": \"" + $__created + "\", \"token_type\": \"bearer\", \"expires_in\": \"" + $expires_in + "\"}"
...
Or even:
...
data: JSON.stringify({access_token: $access_token, refresh_token: $refresh_token, user_id: $user_id, instance_url: "REDACTED", created_at: $created_at, __created: $__created, token_type: "bearer", expires_in: $expires_in})
...
As per the example on here: https://graphql.org/graphql-js/mutations-and-input-types/ (search 'stringify')
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am using Nokogiri to parse XML. I was told to use a CSS selector to search through the XML, but I can't chain it to get through the nested objects.
How do I access the inner elements?
2.6.3 :039 > pp a.css("interface").to_s
"<interface>\n" +
" <status>\n" +
" <__XML__OPT_Cmd_show_interface_status_down>\n" +
" <__XML__OPT_Cmd_show_interface_status___readonly__>\n" +
" <__readonly__>\n" +
" <TABLE_interface>\n" +
" <ROW_interface>\n" +
" <interface>mgmt0</interface>\n" +
" <state>connected</state>\n" +
" <vlan>routed</vlan>\n" +
" <duplex>full</duplex>\n" +
" <speed>a-1000</speed>\n" +
" <type>--</type>\n" +
" </ROW_interface>\n" +
" <ROW_interface>\n" +
" <interface>Vlan1</interface>\n" +
" <state>down</state>\n" +
" <vlan>routed</vlan>\n" +
" <duplex>auto</duplex>\n" +
" <speed>auto</speed>\n" +
" </ROW_interface>\n" +
" <ROW_interface>\n" +
" <interface>Vlan6</interface>\n" +
" <state>down</state>\n" +
" <vlan>routed</vlan>\n" +
" <duplex>auto</duplex>\n" +
" <speed>auto</speed>\n" +
" </ROW_interface>\n" +
" <ROW_interface>\n" +
" <interface>Vlan486</interface>\n" +
" <state>down</state>\n" +
" <vlan>routed</vlan>\n" +
" <duplex>auto</duplex>\n" +
" <speed>auto</speed>\n" +
" </ROW_interface>\n" +
" </TABLE_interface>\n" +
" </__readonly__>\n" +
" </__XML__OPT_Cmd_show_interface_status___readonly__>\n" +
" </__XML__OPT_Cmd_show_interface_status_down>\n" +
" </status>\n" +
" </interface><interface>mgmt0</interface><interface>Vlan1</interface><interface>Vlan6</interface><interface>Vlan486</interface>"
I end up with this tree. What is my XPath here? This is only part of the parsed XML:
2.6.3 :043 > pp parsed
#(DocumentFragment:0x3fce080cd300 {
name = "#document-fragment",
children = [
#(ProcessingInstruction:0x3fce080cce14 { name = "xml" }),
#(Text "\n"),
#(Element:0x3fce080cc7d4 {
name = "rpc-reply",
namespace = #(Namespace:0x3fce080cffb0 {
prefix = "nf",
href = "urn:ietf:params:xml:ns:netconf:base:1.0"
}),
children = [
#(Text "\n" + " "),
#(Element:0x3fce080cf22c {
name = "data",
namespace = #(Namespace:0x3fce080cffb0 {
prefix = "nf",
href = "urn:ietf:params:xml:ns:netconf:base:1.0"
}),
children = [
#(Text "\n" + " "),
#(Element:0x1903f98 {
name = "show",
namespace = #(Namespace:0x1903f20 {
href = "http://www.cisco.com/nxos:1.0:if_manager"
}),
children = [
#(Text "\n" + " "),
#(Element:0x1903700 {
name = "interface",
namespace = #(Namespace:0x1903f20 {
href = "http://www.cisco.com/nxos:1.0:if_manager"
}),
children = [
#(Text "\n" + " "),
#(Element:0x19030fc {
name = "status",
namespace = #(Namespace:0x1903f20 {
href = "http://www.cisco.com/nxos:1.0:if_manager"
}),
children = [
#(Text "\n" + " "),
#(Element:0x1902a1c {
name = "__XML__OPT_Cmd_show_interface_status_down",
namespace = #(Namespace:0x1903f20 {
href = "http://www.cisco.com/nxos:1.0:if_manager"
}),
Your question is really generic and poorly asked so answering a specific question is not possible, but it looks like you need to understand how to access tags in a document using a CSS accessor, which Nokogiri makes very easy.
Meditate on this:
require 'nokogiri'
foo =<<EOT
<tag1>
<tag2>some text</tag2>
<tag3>some more text</tag3>
<tags>something</tags>
<tags>or</tags>
<tags>other</tags>
</tag1>
EOT
xml = Nokogiri::XML.parse(foo)
at finds the first matching occurrence in the document:
xml.at('tag2').content # => "some text"
at is pretty smart, in that it tries to determine whether the accessor is CSS or XPath, so it's a good first tool when you want the first match. If that doesn't work then you can try at_css which specifies that accessor is CSS, because sometimes you can come up with something that could work as CSS or XPath but return different results:
xml.at_css('tag3').content # => "some more text"
xml.at_css('tag3').text # => "some more text"
Similar to at is search, which also tries to determine whether it's CSS or XPath, but finds all matching nodes throughout the document rather than just the first matching one. Because it returns all matching nodes, it returns a NodeSet, unlike at which returns a Node, so you have to be aware that NodeSets behave differently than Nodes when accessing their content or text:
xml.search('tags').text # => "somethingorother"
That's almost never what you want, but you'd be surprised how many people then ask how to split that resulting string into the desired three words. It's usually impossible to do accurately, so a different tactic is needed:
xml.search('tags').map { |t| t.content } # => ["something", "or", "other"]
xml.search('tags').map { |t| t.text } # => ["something", "or", "other"]
xml.search('tags').map(&:text) # => ["something", "or", "other"]
Both at and search have ..._css and ..._xpath variations to help you fine-tune your code's behavior, but I always recommend starting with the generic at and search until you're forced to define what the accessor is.
I also recommend starting with CSS accessors over XPath because they tend to be more readable, and more easily learned if you're working inside HTML with CSS. XPath is very powerful, probably still more so than CSS, but learning it takes longer and often results in less readable code, which affects maintainability.
This is all in the tutorials and cheat sheets and documentation. Nokogiri is extremely powerful but it takes time reading and trying things to learn it. You can also search on SO for other things I've written about searching XML and HTML documents; In particular "What are some examples of using Nokogiri?" helps get an idea how to scrape a page. There's a lot of information covering many different topics related to this. I find it an interesting exercise to parse documents like this as it was part of my professional life for years.
You could use xpath:
parsed = Nokogiri::XML::DocumentFragment.parse(xml)
siamese_cat = parsed.xpath(.//interface/status/state)
Or just iterating thru XML
parsed = Nokogiri::XML::DocumentFragment.parse(xml)
parsed.each do |element|
# Some instructions
end
Well, I have to run the following query (Neo4j comm. ed. 3.0.12 on Docker)
the caveat is that the calendar name has unknown format:
1) firstname + " " + lastname + "-" + specialization
2) lastname + " " + firstname + "-" + specialization
:PARAM name: "Di Pietro Chiara - Gynecologist"
MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25"})
MERGE (_cal_445:`calendar` { :`X-VR-CALNAME` = $name })-[:`belongs_to a`]-(_per_445:`person`)
WHERE $name = _per_445.firstname + " " + _per_445.lastname
OR $name = (_per_445.nome + " " + _per_445.cognome)
RETURN _cal_445, _per_445
The query, and some different variants, doesn't run. Sometimes returns an error, and sometimes destroys the browser layout on the screen,
Surely there is something wrong but I was unable to find and correct.
The part of confronting against two inverted format: how could be optimized?
Why the PARAM declaration generate an error?
Any help will be greatly appreciated.
This part of your query is not valid :
MERGE (_cal_445:`calendar` { :`X-VR-CALNAME` = $name })
You should replace it by this :
MERGE (_cal_445:`calendar` { `:X-VR-CALNAME`:$name })
Moreover, you are doing a MERGE with the value $name that is also on the WHERE cluse. It's just not allowed ...
If you replace the merge by a match, your query will work :
MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25"})
WITH _200
MATCH (_cal_445:`calendar` { `:X-VR-CALNAME`: $name })-[:`belongs_to a`]-(_per_445:`person`)
WHERE $name = _per_445.firstname + " " + _per_445.lastname
OR $name = (_per_445.nome + " " + _per_445.cognome)
RETURN _cal_445, _per_445
I'm building a js file on the backend for future use and need to convert macros into js code. My gsub in the method below was working fine until I had a url with double quotes. If I have a variable quote_type = "'", how can I interpolate that as an escaped quote? In other words..
"'" becomes "\'" and '"' becomes '\"'
Here's my existing method and I just added the quote_type variable to try this out.
def substitute_timestamp_macro!(string)
quote_type = string[0]
string.gsub('[timestamp]', '\' + new Date().getTime() + \'')
end
edit: example string would be "https://doesntmatter.com/stuff/123;time=[timestamp]?"
edit 2: Here is the expected result:
"https://doesntmatter.com/stuff/123;time=" + new Date().getTime() + "?"
here is the actual result
"https://doesntmatter.com/stuff/123;time=' + new Date().getTime() + '?"
notice in my gsub i hard coded an escaped single quote. I now want to use the variable to match the input quote so if it's single, use single, and if double, use double
Consider %() to wrap your string:
def substitute_timestamp_macro!(string)
%("#{string}").gsub("[timestamp]", %(" + new Date().getTime() + "))
end
Note that this will render a string with escaped double quotes:
substitute_timestamp_macro!("https://doesntmatter.com/stuff/123;time=[timestamp]")
=> "\"https://doesntmatter.com/stuff/123;time=\" + new Date().getTime() + \"?\""
Which will be interpreted properly when you render this to a buffer:
puts substitute_timestamp_macro!("https://doesntmatter.com/stuff/123;time=[timestamp]")
=> "https://doesntmatter.com/stuff/123;time=" + new Date().getTime() + "?"
The surrounding quote characters of the value determine the behavior of this function, this should fit the bill:
def substitute_timestamp_macro!(string)
quote_type = string[0]
string.gsub('[timestamp]', "\\#{quote_type} + new Date().getTime() + \\#{quote_type}")
end
I am generating a string from a number of components (title, authors, journal, year, journal volume, journal pages). The idea is that the string will be a citation as so:
#citation = article_title + " " + authors + ". " + journal + " " + year + ";" + journal_volume + ":" + journal_pages
I am guessing that some components occasionally do not exist. I am getting this error:
no implicit conversion of nil into String
Is this indicating that it is trying to build the string and one of the components is nil? If so, is there a neat way to build a string from an array while checking that each element exists to circumvent this issue?
It's easier to use interpolation
#citation = "#{article_title} #{authors}. #{journal} #{year}; #{journal_volume}:#{journal_pages}"
Nils will be substituted as empty strings
array = [
article_title, authors ,journal,
year, journal_volume, journal_pages
]
#citation = "%s %s. %s %s; %s:%s" % array
Use String#% format string method.
Demo
>> "%s: %s" % [ 'fo', nil ]
=> "fo: "
Considering that you presumably are doing this for more than one article, you might consider doing it like so:
SEPARATORS = [" ", ". ", " ", ";", ":", ""]
article = ["Ruby for Fun and Profit", "Matz", "Cool Tools for Coders",
2004, 417, nil]
article.map(&:to_s).zip(SEPARATORS).map(&:join).join
# => "Ruby for Fun and Profit Matz. Cool Tools for Coders 2004;417:"
UPDATE: I thought I had to pass the parameters as a JSON string in the request body, but actually I need to put them on the URL (the endpoint string), so it's working now.
I'm new to Valence. I have some Salesforce Apex code (written by someone else) that creates a D2L user. The code is working fine.
I want to add an Apex method to retrieve info for an existing D2L user using the userName parameter. I've copied the existing method, changed to a GET, set the query parameter to userName, and kept everything else the same.
When I call my method, I get a 403 Invalid Token error.
Do I need to use different authorization parameters for a GET? For example, do I still need to include a timestamp?
Here's a portion of the Salesforce Apex code:
public static final String USERS = '/d2l/api/lp/1.0/users/';
String TIMESTAMP_PARAM_VALUE = String.valueOf(Datetime.now().getTime()).substring(0,10);
String method = GETMETHOD;
String action = USERS;
String signData = method + '&' + action + '&' + TIMESTAMP_PARAM_VALUE;
String userSignature = sign(signData,USER_KEY);
String appSignature = sign(signData,APP_KEY);
String SIGNED_USER_PARAM_VALUE = userSignature;
String SIGNED_APP_PARAM_VALUE = appSignature;
String endPoint = DOMAIN + action + '?' +
APP_ID_PARAM + '=' + APP_ID + '&' +
USER_ID_PARAM + '=' + USER_ID + '&' +
SIGNED_USER_PARAM + '=' + SIGNED_USER_PARAM_VALUE + '&' +
SIGNED_APP_PARAM + '=' + SIGNED_APP_PARAM_VALUE + '&' +
TIMESTAMP_PARAM + '=' + TIMESTAMP_PARAM_VALUE;
HttpRequest req = new HttpRequest();
req.setMethod(method);
req.setTimeout(30000);
req.setEndpoint(endPoint);
req.setBody('{ "orgDefinedId"' + ':' + '"' + person.Id + '" }');
I thought I had to pass the parameters as a JSON string in the request body, but actually I need to put them on the URL (the endpoint string), so it's working now