{
    "componentChunkName": "component---src-templates-blog-post-jsx",
    "path": "/post/knowhow-of-chatwork-api-with-activeresource/",
    "result": {"data":{"site":{"siteMetadata":{"title":"WEB EGG","author":"Leko - CTO at Yuimedi"}},"markdownRemark":{"id":"3cda4013-cb40-5267-8058-c1e30ba41070","excerpt":"れこです。 久々にRubyの記事です。 仕事でよくChatWorkを使用するので、いい加減オレオレAPIクライアントじゃなくてちゃんとしたのを作ろう ということで、ActiveResourceを利用したAPIクライアントを作ってみました。 ActiveResourceは基本的にRuby on Rails…","html":"<p>れこです。<br>\n久々にRubyの記事です。</p>\n<p>仕事でよくChatWorkを使用するので、いい加減オレオレAPIクライアントじゃなくてちゃんとしたのを作ろう<br>\nということで、<a href=\"https://github.com/Leko/activeresource-chatwork\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ActiveResourceを利用したAPIクライアント</a>を作ってみました。</p>\n<p>ActiveResourceは基本的にRuby on Railsで作られたアプリケーション用のAPIクライアントなのですが、汎用的に作られているのでChatWorkのAPIにも対応できました。<br>\nということで他のAPIにもActiveResourceを利用するために備忘録を残しておきます</p>\n<!--more-->\n<h2 id=\"作ったもの\" style=\"position:relative;\"><a href=\"#%E4%BD%9C%E3%81%A3%E3%81%9F%E3%82%82%E3%81%AE\" aria-label=\"作ったもの permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>作ったもの</h2>\n<p>gem化してGithubに上げてあります。</p>\n<blockquote>\n<p><a href=\"https://github.com/Leko/activeresource-chatwork\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GitHub – Leko/activeresource-chatwork: ActiveResource classes for ChatWork API</a></p>\n</blockquote>\n<p>gemの作り方については、<a href=\"http://masarakki.github.io/blog/2014/02/15/how-to-create-gem/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">こちら</a>の記事がとても参考になりました。</p>\n<h2 id=\"リクエストレスポンスの共通部分\" style=\"position:relative;\"><a href=\"#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%81%AE%E5%85%B1%E9%80%9A%E9%83%A8%E5%88%86\" aria-label=\"リクエストレスポンスの共通部分 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>リクエスト/レスポンスの共通部分</h2>\n<p>ChatWorkのAPIは、リクエストは<code>x-www-form-urlencoded</code>に対しレスポンスは<code>application/json</code>という特殊な要件なので、<br>\n<code>ActiveResource::Formats::JsonFormat</code>を拡張したフォーマッタを作成しました。</p>\n<p>リポジトリの<a href=\"https://github.com/Leko/activeresource-chatwork/blob/master/lib/chatwork/base.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lib/chatwork/base.rb</a>に定義してます。コードはこんな感じ。</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">FormToJsonParser</span>\n  <span class=\"token keyword\">include</span> <span class=\"token constant\">ActiveResource</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">Formats</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">JsonFormat</span>\n\n  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">mime_type</span></span>\n    <span class=\"token string\">'application/x-www-form-urlencoded'</span>\n  <span class=\"token keyword\">end</span>\n\n  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">decode</span></span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span>\n    <span class=\"token constant\">ActiveSupport</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">end</span>\n<span class=\"token keyword\">end</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Base</span> <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ActiveResource</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">Base</span>\n  <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>format <span class=\"token operator\">=</span> <span class=\"token constant\">FormToJsonParser</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">new</span>\n\n  <span class=\"token comment\"># ...</span>\n\n  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">to_json</span></span><span class=\"token punctuation\">(</span>options <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    json <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> include_root_in_json\n             <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> root<span class=\"token punctuation\">:</span> <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">.</span>element_name <span class=\"token punctuation\">}</span><span class=\"token punctuation\">.</span>merge<span class=\"token punctuation\">(</span>options<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n           <span class=\"token keyword\">else</span>\n             <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>options<span class=\"token punctuation\">)</span>\n           <span class=\"token keyword\">end</span>\n    hash <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span>\n\n    <span class=\"token constant\">URI</span><span class=\"token punctuation\">.</span>encode_www_form<span class=\"token punctuation\">(</span>hash<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">end</span>\n<span class=\"token keyword\">end</span></code></pre></div>\n<h2 id=\"url末尾からjson等のフォーマットを消したい\" style=\"position:relative;\"><a href=\"#url%E6%9C%AB%E5%B0%BE%E3%81%8B%E3%82%89json%E7%AD%89%E3%81%AE%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E3%82%92%E6%B6%88%E3%81%97%E3%81%9F%E3%81%84\" aria-label=\"url末尾からjson等のフォーマットを消したい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>URL末尾から.json等のフォーマットを消したい</h2>\n<p><a href=\"https://github.com/rails/activeresource/blob/master/lib/active_resource/base.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ActiveResource::Base#format_extension</a>を読んでいたら発見。</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Base</span> <span class=\"token operator\">&lt;</span> <span class=\"token constant\">ActiveResource</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">Base</span>\n  <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>include_format_in_path <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span>\n<span class=\"token keyword\">end</span></code></pre></div>\n<p>で対応できました。</p>\n<h2 id=\"ネストしたリソースを扱いたい\" style=\"position:relative;\"><a href=\"#%E3%83%8D%E3%82%B9%E3%83%88%E3%81%97%E3%81%9F%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%92%E6%89%B1%E3%81%84%E3%81%9F%E3%81%84\" aria-label=\"ネストしたリソースを扱いたい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ネストしたリソースを扱いたい</h2>\n<p>ChatWorkは<code>/v1/rooms/:room_id/messages/:message_id</code>のように、ネストしたルーティングが必要になります。<br>\nActiveResourceにはActiveRecordのように<a href=\"https://github.com/rails/activeresource#associations\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">リレーション</a>の機能があるようですが、一部要件を満たせなかった(※後述)ので、下記の記事も参考にしつつ試してみました。</p>\n<blockquote>\n<p><a href=\"http://blog.revathskumar.com/2013/12/activeresource-passing-prefix-options.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ActiveResource : Passing prefix options</a><br>\nちなみに情報が古いのか<code>update_attributes</code>に関しては上手く動きませんでした。</p>\n</blockquote>\n<p>リポジトリの<a href=\"https://github.com/Leko/activeresource-chatwork/blob/master/lib/chatwork/message.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lib/chatwork/message.rb</a>に実装例が有りますが、大枠としては</p>\n<ul>\n<li><code>prefix</code>プロパティに<code>:hoge_id</code>のように:付きのパスを定義する</li>\n<li><code>params</code>に<code>hoge_id</code>を指定する</li>\n</ul>\n<p>has_many的なものは</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\">has_many <span class=\"token symbol\">:members</span><span class=\"token punctuation\">,</span> class_name<span class=\"token punctuation\">:</span> <span class=\"token string\">'chatwork/member'</span></code></pre></div>\n<p>で定義できます。<br>\n<code>class_name</code>オプションを渡さないと、クラスが定義されている名前空間によらずトップレベルの名前空間が指定されてしまうので注意です。<br>\n<strong>注意点として、この方法ではクエリパラメータを渡すことが出来ません</strong> 解決方法は後述します。</p>\n<p>belongs_to的なものは、残念ながらChatWorkでは意図したとおりに動きません。<br>\nこれも後述します。</p>\n<p>利用方法は<a href=\"https://github.com/Leko/activeresource-chatwork/tree/master/spec/chatwork\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">テスト</a>を見ていただくほうが早いと思います。</p>\n<h2 id=\"クエリパラメータが必要なhas_manyを作りたい\" style=\"position:relative;\"><a href=\"#%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%AAhas_many%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%9F%E3%81%84\" aria-label=\"クエリパラメータが必要なhas_manyを作りたい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>クエリパラメータが必要なhas_manyを作りたい</h2>\n<p><code>has_many</code>はオプション引数を受け取ってくれないので、クエリパラメータが必要な場合、has_manyを利用することが出来ません。<br>\nということでリレーションが使えないならメソッドを自作します。<br>\n実装にあたり、下記の記事がとても参考になりました。</p>\n<blockquote>\n<p><a href=\"http://wholemeal.co.nz/blog/2010/03/08/active-resource-associations-and-nested-resources/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">wholemeal: Active Resource - Associations and Nested Resources</a></p>\n</blockquote>\n<p><a href=\"https://github.com/Leko/activeresource-chatwork/blob/master/lib/chatwork/room.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lib/chatwork/room.rb</a>に定義してます。</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">messages</span></span><span class=\"token punctuation\">(</span>params <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token constant\">Message</span><span class=\"token punctuation\">.</span>all<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">:</span> subroute_params<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">end</span></code></pre></div>\n<p>という感じに、リレーションっぽいメソッド名で<code>.all</code>や<code>.find</code>、<code>.first</code>等を使用してそれっぽく見せてます。<br>\nちなみに多用すると <strong>N+1のHTTPリクエスト</strong> という甚大なボトルネックが生まれます。<br>\nまぁHTTP+ActiveResourceではSQL+ActiveRecordのような柔軟さは実現できないので、性能に難が出ない程度にすっぱり諦めた方が良いと思います。。。</p>\n<h2 id=\"レスポンスに主キーがなくてもbelongs_toしたい\" style=\"position:relative;\"><a href=\"#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%81%AB%E4%B8%BB%E3%82%AD%E3%83%BC%E3%81%8C%E3%81%AA%E3%81%8F%E3%81%A6%E3%82%82belongs_to%E3%81%97%E3%81%9F%E3%81%84\" aria-label=\"レスポンスに主キーがなくてもbelongs_toしたい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>レスポンスに主キーがなくてもbelongs_toしたい</h2>\n<p>おそらくActiveResourceは</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># /users/1.json</span>\n<span class=\"token punctuation\">{</span> id<span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">:</span> <span class=\"token string\">'xxx'</span> <span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\"># /users/1/comments.json</span>\n<span class=\"token punctuation\">{</span> id<span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> user_id<span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">:</span> <span class=\"token string\">'xxx'</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<p>のようなものを想定しているため、レスポンスの中に<code>user_id</code>に相当するフィールドがないとcommentsからuserを見ることが出来ません。</p>\n<p>ChatWorkでの例に置き換えると、<br>\n<code>/rooms/:room_id/members</code>のレスポンスに<code>room_id</code>が含まれていないので、belongs_toでは紐付けが出来ません。<br>\n<code>belongs_to</code>はパスを生成する時にレスポンスの中身しか見てくれないないようです。なぜか<code>prefix_options</code>を見てくれません。<br>\nということでメソッドを自作します。</p>\n<p><a href=\"https://github.com/Leko/activeresource-chatwork/blob/master/lib/chatwork/nest_of_room.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lib/chatwork/nest_of_room.rb</a>に定義してます。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">module ChatWork\n  module NestOfRoom\n    def room\n      Room.find(prefix_options[:room_id])\n    end\n  end\nend\n\nmodule ChatWork\n  class Member &lt; Base\n    include ChatWork::NestOfRoom\n  end\nend</code></pre></div>\n<p>という感じで、<code>prefix_options</code>を使ってRoom.findすれば、レスポンスにroom_idが無くてもなんとかできます。</p>\n<h2 id=\"railsのルーティングに反するurlに対応したい\" style=\"position:relative;\"><a href=\"#rails%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AB%E5%8F%8D%E3%81%99%E3%82%8Burl%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%9F%E3%81%84\" aria-label=\"railsのルーティングに反するurlに対応したい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Railsのルーティングに反するURLに対応したい</h2>\n<p><code>/v1/my/tasks</code>のように、Railsのルーティングに対応してないURLもなんとかしたい。<br>\nActiveResourceには<a href=\"http://api.rubyonrails.org/v3.2.6/classes/ActiveResource/CustomMethods.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">カスタムメソッド</a>の機能があります。</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># {ActiveResource::Baseを継承したクラス}.{HTTPメソッド(小文字)}(:パス, オプション)</span>\n<span class=\"token constant\">ChatWork</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">My</span><span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token symbol\">:tasks</span><span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">:</span> <span class=\"token string\">'open'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>という感じで、ただのHTTPクライアント的な使い方もできるようです。<br>\n戻り値が配列だったら<code>Array</code>、戻り値がオブジェクトなら<code>Hash</code>のインスタンスが返るようです。<br>\nこのままではActiveResourceのメソッド郡が使えないのでなんとかしたい。。。</p>\n<h2 id=\"カスタムメソッドでもactiveresourcebaseのインスタンスを返したい\" style=\"position:relative;\"><a href=\"#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A7%E3%82%82activeresourcebase%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%92%E8%BF%94%E3%81%97%E3%81%9F%E3%81%84\" aria-label=\"カスタムメソッドでもactiveresourcebaseのインスタンスを返したい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>カスタムメソッドでもActiveResource::Baseのインスタンスを返したい</h2>\n<p>カスタムメソッドを使うとHashかArrayになってしまうので、なんとかしたい。<br>\nActiveResource::Base.newはHashを受け取るので、受け取ったレスポンスをそのまま渡せます。<br>\nつまりゴリ押しです。もしかしたら相当するオプションが有るのかもしれません。</p>\n<p><a href=\"https://github.com/Leko/activeresource-chatwork/blob/master/lib/chatwork/my.rb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lib/chatwork/my.rb</a>に定義してます</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span><span class=\"token function\">tasks</span></span><span class=\"token punctuation\">(</span>params <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n      get<span class=\"token punctuation\">(</span><span class=\"token symbol\">:tasks</span><span class=\"token punctuation\">,</span> params<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>map <span class=\"token punctuation\">{</span> <span class=\"token operator\">|</span>t<span class=\"token operator\">|</span> <span class=\"token constant\">ChatWork</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token constant\">Task</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">new</span><span class=\"token punctuation\">(</span>t<span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">end</span></code></pre></div>\n<p>これを応用すれば、レスポンスを任意のクラスに変換できそうです。<br>\n件数の多いAPIだと.newのオーバーヘッドが地味にありそうなので、ご利用は計画的に。</p>\n<h2 id=\"主キーに相当するフィールド名を上書きしたい\" style=\"position:relative;\"><a href=\"#%E4%B8%BB%E3%82%AD%E3%83%BC%E3%81%AB%E7%9B%B8%E5%BD%93%E3%81%99%E3%82%8B%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E5%90%8D%E3%82%92%E4%B8%8A%E6%9B%B8%E3%81%8D%E3%81%97%E3%81%9F%E3%81%84\" aria-label=\"主キーに相当するフィールド名を上書きしたい permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>主キーに相当するフィールド名を上書きしたい</h2>\n<p>デフォルトだとレスポンス内の<code>id</code>というフィールドを主キーと見なす、という作りになっています。<br>\nChatWorkでいえば、<code>/rooms</code>のレスポンス内の主キーは<code>room_id</code>というフィールド名になっています。<br>\nこのままではフィールド名が噛み合わず<code>save</code>や<code>destroy</code>の挙動に支障をきたします。</p>\n<p>これを上書きするには、<code>primary_key</code>というプロパティを変更します。</p>\n<div class=\"gatsby-highlight\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>primary_key <span class=\"token operator\">=</span> <span class=\"token string\">'room_id'</span></code></pre></div>\n<p>こうすれば、レスポンス内部にidというキーがなくてもマッピングしてくれました。</p>\n<h2 id=\"まとめ\" style=\"position:relative;\"><a href=\"#%E3%81%BE%E3%81%A8%E3%82%81\" aria-label=\"まとめ permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>まとめ</h2>\n<p>やはりRailsでないアプリケーションにActiveResourceを対応させるのは少々無理が生じるようです。<br>\nそれでもChatWorkのURL構造はだいぶRailsにRESTfulな感じなので、比較的軽度に収まりました。<br>\nもしオレオレ全開なAPIに対応するとしたら、カスタムメソッドを多用することになりそうだなぁ、、、と感じました。</p>\n<p>この内容が、少しでもActiveResourceでRails以外のAPIクライアントを作るときの助けになれば幸いです。</p>","timeToRead":10,"frontmatter":{"title":"ActiveResourceでChatWorkのAPIクライアントを作る際にハマったところと解決策","tags":["ActiveResource","ChatWork","Ruby"],"date":"September 26, 2016","featuredImage":null}}},"pageContext":{"slug":"/knowhow-of-chatwork-api-with-activeresource/","previous":{"fields":{"slug":"/event-report-of-isucon-2016/"},"frontmatter":{"title":"ISUCON 2016に参加してスコア40700点で予選敗退した","tags":["ISUCON"]}},"next":{"fields":{"slug":"/automate-deploy-to-rubygems-with-circleci/"},"frontmatter":{"title":"RubygemsへのデプロイをCircleCIで自動化してみた","tags":["CircleCI","Ruby","Rubygems"]}}}},
    "staticQueryHashes": ["2585454260","2954598359"]}