Заменить на экранированную строку оболочки? - PullRequest
0 голосов
/ 31 мая 2018

Я хочу заменить переменную ruby ​​на экранированную строку оболочки.

Это то, с чего я начинаю, и это работает:

<<~`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

Я попал в ловушку между экранированием двух языков.

Все это обходной путь размещения вложенного json в ruby.Flat jsons работает в большинстве гемов http, но получение вложенного json является редкой необходимостью, и я боюсь, что большинство гемов не проверяли его (я помню, что пытался это сделать с помощью http.rb, но даже массив json )нетривиально там .

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Я думаю, что вы выбрали неправильный подход.Смешивание интерполяции строк с обратными метками или версия с одним аргументом Kernel#system грязно и опасно.Вам лучше полностью обойти оболочку и проблемы с ее цитированием и использовать форму с несколькими аргументами 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 с предоставленнымаргументы без участия оболочки вообще.Если вам нужно сохранить ответ curl, используйте Open3 из стандартной библиотеки и снова избегайте оболочки и проблем с ее цитированием.

0 голосов
/ 31 мая 2018

Чтобы решить вашу проблему, вы должны быть осторожны, избегая всего с 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

Но это утомительно и подвержено ошибкам, а на самом деле не ваша проблема.

Все это обходной путь публикации вложенного json в ruby.Flat 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 вручную.Как и в случае с curl, это подвержено ошибкам.


Вместо этого создайте хэш 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}" }
)

Или, что еще лучше, использовать canvas-api gem , который заботится опреобразование JSON и может использовать функции API, такие как нумерация страниц.

canvas = Canvas::API.new(:host => CANVAS_URI, :token => CANVAS_TOKEN)
response = canvas.post(
    "/api/v1/courses/#{COURSE_ID}/quizzes/#{quiz_id}/questions",
    payload
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...