読者です 読者をやめる 読者になる 読者になる

>& STDOUT

主にソフトウェアに関する日々の標準出力+標準エラー出力

RedmineのREST APIで特定プロジェクトの全チケットを取得しようとして失敗する

出来そうで出来ない、かゆいところにいつもあと1センチ届かない、RedmineREST APIの振り回されメモ。

基本形

チケットの情報を取るときはRedmineのApplication Rootから issues.xml にパラメータ渡してGETが基本的な形(issues.jsonでも可)。API_ACCESS_KEY は個人設定のページで各自発行できます。

https://redmine.server.com/redmine/issues.xml?key=API_ACCESS_KEY&project_id=PROJECT_ID&limit=100&page=1

この時limitを指定しないと先頭から25件しか取得できないことに注意。
チケットが100件以上あるプロジェクトでも、一度に取得できるのは100件まで

で、前述のリクエストを投げるとこんなのがルート要素として返ってきます。

<issues total_count="471" offset="0" limit="100" type="array">

この total_count を limit で割った数(+1)だけ page があります。よって、この例では先頭のリクエストの page パラメータを 1〜5 までカウントアップしながら、5回リクエストを投げないと「全てのチケット」は取得出来ない、ということです。面倒ですね。

ページ数分リクエストする

考え方としてはざっくり↓こんな感じ。(リクエスト1回多いですが、やってることわかり易く。

request_url = "https://redmine.server.com/redmine/issues.xml?key=API_ACCESS_KEY&project_id=PROJECT_ID&limit=100&page=1"
response = http.request(request_url) #https対応のclient作っておく
xml = Nokogiri::HTML.parse(response.body, nil, "UTF-8")
total_count = xml.css("issues").attribute("total_count").value
limit = xml.css("issues").attribute("limit").value
pages = total_count.to_i / limit.to_i + 1 #何ページ(=何回)リクエストするのか計算

pages.times do |page_number|
  request_url = "https://redmine.server.com/redmine/issues.xml??status_id=*&key=API_ACCESS_KEY&project_id=PROJECT_ID&limit=100&page=#{page_number + 1}"
  response = http.request(request_url) 
  full_xml << response.body
end

ところがどっこい

とりあえずこれで full_xml に「そのプロジェクトのチケット全部」が入る、、、ハズだったのが、なんと status_id=*(OpenとClosedを両方とる) が効かずにOpenしか取ってこれていないことが判明(Redmine 2.3.1.stable)。燃え尽きたよとっつぁん。

落ち込んだりもしたけれど

いまは CSV Export で元気です。たぶん。

追記

status_id=* はURLエンコードしてあげないとダメっぽいです。status_id=%2a。で、これで全部取れたとしても5個のxmlなりjsonなりを結合してからFull Parseという手数が待ってますので、CSV Export から二次元配列をゴニョゴニョしたほうが早く感じるのはトシなんですかね…。