我想将ruby变量替换为转义的shell字符串。
这就是我的开始,它的确有效:
<<~`SHELL`
curl -s "#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "question": { "question_type": "multiple_choice_question", "question_text": "<p>Is everything clear?</p>", "points_possible": 1, "answers": [ { "text": "I read and understood", "html": "", "weight": 100 }, { "text": "I have questions", "comments_html": "<p>Please post your questions to a discussion (in course navigation).</p>", "weight": 0 } ] } }' \
-H "Authorization: Bearer #{CANVAS_TOKEN}"
SHELL
但我希望discussion
(在-d JSON
中)成为链接。而且无法让它发挥作用:
myJson = %Q|{ "question": { "question_type": "multiple_choice_question", "question_text": "<p>Is everything clear?</p>", "points_possible": 1, "answers": [ { "text": "I read and understood", "html": "", "weight": 100 }, { "text": "I have questions", "comments_html": "<p>Please post your questions to a <a href="#{CANVAS_URI}/courses/#{COURSE_ID}/discussion_topics">discussion</a>.</p>", "weight": 0 } ] } }|
<<~`SHELL`
curl -s "#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions" \
-X POST \
-H "Content-Type: application/json" \
-d '#{myJson}' \
-H "Authorization: Bearer #{CANVAS_TOKEN}"
SHELL
<<~`SHELL`
curl -s "#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions" \
-X POST \
-H "Content-Type: application/json" \
-d "#{myJson}" \
-H "Authorization: Bearer #{CANVAS_TOKEN}"
SHELL
我被困在逃离两个郎之间。
整个事情是在ruby中发布嵌套json的解决方法。平面jsons适用于大多数http宝石,但是获得嵌套json是一种罕见的需求,我担心大多数宝石都没有测试它(我记得尝试使用http.rb来做到这一点,但即使是json数组也是{ {3}}
答案 0 :(得分:3)
要解决您的问题,您必须小心使用Shellwords.escape
来逃避所有问题,然后不要引用它们。
<<~`SHELL`
curl -s "#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions" \
-X POST \
-H "Content-Type: application/json" \
-d #{Shellwords.escape(myJson)} \
-H "Authorization: Bearer #{CANVAS_TOKEN}"
SHELL
但这很乏味且容易出错,而不是你的问题。
整个过程是在ruby中发布嵌套json的一种解决方法。平面jsons适用于大多数http宝石,但获得嵌套json是一种罕见的需求,我担心大多数宝石都没有测试它......
嵌套的JSON并不罕见,无论如何,http客户端都没有理由关心JSON的内容。它只是传输一个字符串。
您的JSON格式不正确。具体在这里:
"comments_html": "<p>Please post your questions to a <a href="#{CANVAS_URI}/courses/#{COURSE_ID}/discussion_topics">discussion</a>.</p>"
你有一个未转义的报价。这可能是因为您手动将嵌套的JSON放在一起。就像炮击卷曲一样,这很容易出错。
相反,创建一个Ruby哈希并将其转换为JSON。然后,您将获得Ruby语法检查的所有好处。
payload = {
question: {
question_type: "multiple_choice_question",
question_text: "<p>Is everything clear?</p>",
points_possible: 1,
answers: [
{
text: "I read and understood",
html: "",
weight: 100
}, {
text: "I have questions",
comments_html: %Q[<p>Please post your questions to a <a href="#{CANVAS_URI}/courses/#{COURSE_ID}/discussion_topics">discussion</a>.</p>],
weight: 0
}
]
}
}
require "json"
json_payload = JSON.generate(payload)
而不是调用curl
,而是使用http库。由于您正在调用REST API,因此可以使用RestClient。
require "rest-client"
response = RestClient.post(
"#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions",
json_payload,
{ content_type: :json, authorization: "Bearer #{CANVAS_TOKEN}" }
)
或者,更好的是,使用负责JSON转换的canvas-api gem并利用分页等API功能。
canvas = Canvas::API.new(:host => CANVAS_URI, :token => CANVAS_TOKEN)
response = canvas.post(
"/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions",
payload
)
答案 1 :(得分:3)
我认为你采取了错误的做法。将字符串插值与反引号或Kernel#system
的单个参数版本混合是混乱和危险的。你最好完全绕过shell及其引用问题并使用system
的多参数形式:
system(
'curl',
'-s', "#{CANVAS_URI}/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions",
'-X', 'POST',
'-H', "Content-Type: application/json",
'-d', myJson,
'-H', "Authorization: Bearer #{CANVAS_TOKEN}"
)
这将使用提供的参数直接执行curl
,而根本不涉及shell。如果您需要保存curl
的响应,请使用标准库中的Open3
,然后再次避免shell及其引用问题。