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

歩いたら休め

If the implementation is easy to explain, it may be a good idea.

【R】R6ライブラリを使ってクラスを作ってChatworkのAPIを叩いてみた

R R6

Pythonでプログラミングする際、「まずコードを書いて、ある程度コードが大きくなってきたらクラスを作って整理する」ということをよくします。

R言語ではなんだかオブジェクト指向の概念が特殊で、その辺の機能を敬遠していましたが、 「普通のオブジェクト指向言語っぽくプログラミングできるR6というライブラリがあるらしい」 と聞きました。

qiita.com

[http://www.slideshare.net/nakamichi/r6-upload:embed:cite]

そこで練習半分、R6を使ってプログラムを書いてみました。 下の記事にある「ChatworkのAPIを叩いてメッセージを投稿する」プログラムをOOPっぽく書きました。

kiito.hatenablog.com

Python等に慣れている人なら、あまり違和感なく利用できると思います。 publicとかprivateにlistで関数を与えるのって、なんだかJavaScriptのコードみたいな見た目になりますね。

library(R6)
library(utils)
library(RCurl)
library(rjson)

api <- R6::R6Class("api",
  public = list(
    initialize = function(access_token) {
      private$access_token <- access_token
    },

    # room_idの部屋にメッセージを投稿する
    post_messages = function(message, room_id) {
      result <- RCurl::postForm(
        uri = private$make_uri('rooms', room_id, 'messages'),
        .opts = list(
          httpheader = private$make_header(),
          postfields = private$make_body(message)
        )
      )
      return(
        rjson::fromJSON(result)
      )
    },

    # room_idの部屋にメッセージを取得する
    get_messages = function(room_id, force = FALSE) {
      result <- RCurl::getForm(
        uri = paste0(
          private$make_uri('rooms', room_id, 'messages'),
          ifelse(force, '?force=1', '?force=0') # とりあえずifelse関数(三項演算子みたいなもの)で
        ),
        .opts = list(
          httpheader = private$make_header()
        )
      )
      return (
        rjson::fromJSON(result) # jsonをparseする。dataframeの形に成形したほうがいいかな…
      )
    }
  ),
  
  private = list(
    access_token = NA,
    url = 'https://api.chatwork.com/v1',
    
    make_header = function() {
      return (
        c('X-ChatWorkToken' = private$access_token)
      )
    },

    # ChatworkのAPIの種類によってURIの階層の長さが違うので、可変長引数で文字列を渡して"/"区切りに変換する関数を用意
    make_uri = function(...) { 
      return (
        Reduce(
          function(x, y){paste(x, y, sep='/')},
          as.character(list(private$url, ...))
        )
      )
    },
    
    make_body = function(message) {
      return (
        utils::URLencode(paste0('body=', message))
        # win環境では utils::URLencode(iconv(paste0('body=', message), 'SHIFT_JIS','UTF-8'))
      )
    }
  )
)

# インスタンスを作る
client <- api$new(access_token = '82*************')

# Chatworkにメッセージを投稿してみる
client$post_messages(message = 'Hello Chatwork!', room_id = 41******)
# $message_id
# [1] 995512653

# チャットのメッセージ一覧を取得
# force = TRUEで、未取得にかかわらず最新の100件を取得
messages <- client$get_messages(room_id = 41******, force = TRUE)

暇があったらライブラリ化してみたいですね。