Qiita版TweetDeck！？カラム形式でQiita記事をウォッチできるクライアントサービス「QiitaDeck」をリリースしました！

![QiitaDeck-top.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/5de57647-bdfb-8161-c40b-2ef21d8d5062.gif)
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">.<a href="https://twitter.com/kazu_real20?ref_src=twsrc%5Etfw">@kazu_real20</a> と共同で「QiitaDeck」という&quot;もっとQiitaで情報収集しやすく！&quot;をコンセプトに「気になる人、気になるタグ、今のトレンド」をリアルタイムウォッチできるWebサービスをリリースしました🎉<a href="https://t.co/yjl9nc2Qm4">https://t.co/yjl9nc2Qm4</a> <a href="https://twitter.com/qiitadeck?ref_src=twsrc%5Etfw">@qiitadeck</a> <br><br>ぜひとも！<a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AB%E5%B1%8A%E3%81%91?src=hash&amp;ref_src=twsrc%5Etfw">#プログラマに届け</a><a href="https://twitter.com/hashtag/%E6%8B%A1%E6%95%A3%E5%B8%8C%E6%9C%9B?src=hash&amp;ref_src=twsrc%5Etfw">#拡散希望</a><a href="https://twitter.com/hashtag/QiitaDeck?src=hash&amp;ref_src=twsrc%5Etfw">#QiitaDeck</a> <a href="https://t.co/fzqbaNhOVU">pic.twitter.com/fzqbaNhOVU</a></p>&mdash; ISSY! (@issy_s16) <a href="https://twitter.com/issy_s16/status/1054557069464879106?ref_src=twsrc%5Etfw">2018年10月23日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

「**Qiitaをもっと使いやすく**」をコンセプトに、Qiitaの記事をリアルタイムでウォッチできるサービス「**QiitaDeck**」をリリースしました:raised_hands:
Qiitaのアカウント１つ持っていれば、すぐにでも使い始めることができます！

:link:　[QiitaDeck - もっとQiitaで情報収集！](https://qiitadeck.com/)
##:gem:QiitaDeckでできること
###:star2:ウォッチできる記事の種類
- **トレンド記事**
![qiitadeck_tutorial_getTrend.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/9c19906d-095c-1288-0383-7fb405f1d1ee.gif)
デイリートレンド記事をウォッチすることができます。

- **気になるユーザーのストック記事**
![qiitadeck_tutorial_searchStock.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/e5ff482e-b5fe-dc10-d398-b0906ce14a6f.gif)
気になるユーザーのストックした記事をウォッチすることができます。

- **気になるタグのついた記事**
![qiitadeck_tutorial_seachTag.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/750499ef-cc09-c21c-f704-78d4a355664e.gif)
気になるタグのついた記事を新着順でウォッチすることができます。

###その他機能
- **記事作成ページへの移動**
![qiitadeck_tutorial_new.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/d4559e29-4f9b-fd01-91a1-55cd39e824d1.gif)
「記事書きたい！」となったときでも、すぐに記事作成画面に移動することができます。

- **下書きページへの移動**
![qiitadeck_tutorial_draft.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/356c5f37-a092-406c-a5c5-f68e02d57ba5.gif)
下書き一覧ページへの移動もできます。

このように、**トレンド記事**、**気になるユーザーのストック記事**、**気になるタグがついた記事**の新着記事をリアルタイムで管理することができます。
QiitaDeckについての新規機能実装などのお知らせは公式ツイッターアカウントにて呟いております。
:link:[ QiitaDeck公式ツイッターアカウント](https://twitter.com/qiitadeck)

##:writing_hand:開発するまでに至った経緯
プログラミングを本格的に始めて４ヶ月が経ったということで、今の技量で何か作ってみたいと思ったのと、同時期にエンジニアインターンとして働き始めたこともあり、インターン先の主要フレームワークである"Ruby on Rails"の勉強もしなければならないことから、「それならWebサービスを作ろう」と思い至りました。

そこで何を作ろうかと考えたときに、Qiitaを本格的に利用し始めた頃から気になっていたこと

**（QiitaにもTweetDeckのように様々なジャンルの記事を一元管理できたらもっとリアルタイムに情報収集できるようになるのでは...）**

を思い出し、これだ！ということでQiitaDeckの開発をすると決意しました。

しかし、作ろうとなったのは良いものの、今までWebサービスを作ったことがなかった為、何から手をつければいいのかさっぱりわかりませんでした。
そこで、バックエンドエンジニアとして活躍している兄（@issy_s16）にその思いを相談したところ、お互いの勉強にもなるし！ということで共同で開発することになりました。

##:gear:技術的な部分
###:wrench:使用技術
- Ruby  Ruby on Rails 
- HTML / CSS(SCSS) / JavaScript(jQuery)
- QiitaAPI
- Git  GitHub
- CircleCI
- ConoHa VPS

####Ruby on Railsを採用した理由
先述しましたが、本サービスの開発に着手し始めたのと同じ頃からエンジニアインターンとして働き始めたこともあり、インターン先の主要フレームワークである"Ruby on Rails"の勉強もしなければと考えていたので、フレームワークはRuby on Railsを採用しました。

####QiitaAPIを用いたOAuth実装、記事情報取得
Qiitaアカウントでのログイン機能の実装、Qiitaのタグに紐付いた記事やユーザーのストック記事情報の取得をするために"QiitaAPI"を用いました。
ストック記事の取得にはQiitaAPIが用意されていなかったため、一定間隔でスクレイピングし、記事要素を抽出するようにしています。
:link:[ QiitaAPI](https://qiita.com/api/v2/docs)

####ConoHaを採用した理由
今回なぜ"[ConoHa](https://www.conoha.jp/)"を採用したのかというと、

- まず何より安い！（630円/月）
- 以前ConoHa用コマンドラインツール「ConoHa-CLI」を個人開発したとき、非常に便利で且つ使いやすいと感じたから
- このはちゃんがかわいい！

の３点があったからです。

(ConoHa-CLIについてはこちらの記事にまとめてあります)
:link:[ ConoHa用コマンドラインツール(CLI)を公開したよ！](https://qiita.com/issy_s16/items/964dd9430fe29710013b)

###:orange_book:使用したライブラリについて
####Sortable.js
![aaaa.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/63099f9c-febe-3b77-ec2e-b9001edbdb5e.gif)
カラムをドラッグ＆ドロップで移動できる機能は**"Sortable.js"**ライブラリを用いて実装しました。
:link:[ GitHub | Sortable.js](https://github.com/RubaXa/Sortable)

実装方法については、以下のサイトを参考にさせていただきました。
:link:[ ドラッグ＆ドロップで要素を並び替えることができるSortable.js](https://spyweb.media/2017/11/02/js-drag-and-drop-sortable-plugin/)

カラム移動後にカラム状態を保存する機能について軽くご説明します。
"Sortable.js"には様々なイベントが用意されています。(下記記事にて詳しく説明されているため、イベントについては本記事では割愛させていただきます。)
:link:[ 【jQueryUIを使わずにドラッグ＆ドロップを実装したい】Javascriptライブラリ「Sortable」を使ってみた](https://qiita.com/AVELWP/items/536c797a63c081cf7bc0)

```javascript:Sortable_example.js
// ソート処理
  $(function() {
    Sortable.create($('.list')[0], {
      animation: 200, // ソート時のアニメーションスピード
      onUpdate: function(){
        var updated_column = []; // ソート後のカラム情報を格納する為の配列
        $('.item').each(function(){
          var type = $(this).children('ul').attr("カラムのタイプ（Ex:trend）");
          var data = $(this).children('ul').attr("カラムのデータ(Ex:daily)");
          updated_column.push({data: data, type: type});
        });
        // 事前に用意しておいたカラム状態を更新するためのAPIにPOSTでデータを渡す
        $.post('/api/v1/column/update', {
          column: updated_column
        });
      }
    });
  })
```
今回は**"onUpdate"**イベントを用いて、カラム移動完了後に移動後のカラム情報を取得し、そのデータを基にDB内に格納されているカラム状態の更新処理を実行するようにしました。
これにより、ソート後のカラム状態を保持する機能を実装することができました。

####bxSlider.js
機能説明（チュートリアル）の見やすさ向上の為に、モーダルウィンドウ内にスライダー機能を実装することにしました。
![Oct-25-2018 03-21-33.gif](https://qiita-image-store.s3.amazonaws.com/0/278959/7481c642-2e18-b608-4486-9fa83d389873.gif)
スライダー機能の実装に**"bxSlider.js"**ライブラリを使用しました。
:link:[ bxSlider.js](https://bxslider.com/)
使用した理由としては、普段から使用していることもあり、仕様をある程度理解していた為です。

下記サイトに、"bxSlider.js"の実装方法からオプション一覧まで事細かく説明されているため、実装方法が知りたい場合はとても参考になると思います！
:link:[ 【jQuery】超簡単jQueryスライダー［bxSlider］の使い方。](https://on-ze.com/archives/1658)

このライブラリに悩まされたことは、**たまにスライダー領域の高さが０の状態で表示される（つまり表示されない）**ことと**一枚目のスライド要素が数px横にずれた状態で表示される**ことです。
高さが０になるバグは、JavaScriptで高さが０になっているクラスに後付けでCSSを当てる方法で完全にではありませんが概ね正常に表示させられるようにできました。
スライダーの要素が数ピクセルずれる問題は、スライダー領域のmarginとpaddingを一旦０と指定ことで解消することができました。

```javascript:bxSlider_fixedBug.js
// bxsliderバグ解消用
  $(window).load(function(){
    var width = $(this).width();
    if(width <= 768){
      // SP（スマートフォン）の場合
      $(".bx-viewport").css("height", "指定したいpx");
    } else{
      // PCの場合
      $(".bx-viewport").css("height", "指定したいpx");
    }
  })
```
こちらが高さが０になるバグを概ね解決に近づけることができたコードです。
今回は、SPとPCでスライダー領域の高さが変わるため、このように条件分岐をして高さを指定しています。
##:point_up:こだわった点
**"Qiitaを普段からよく利用する方にこそ使って頂きたいサービス"**ということもあったので、"Qiitaを触っている"という感覚を極力損なわないようにするために、Qiitaのカラーに合わせたデザインにしました。
![FireShot Capture 7 - QiitaDeck - https___qiitadeck.com_#.png](https://qiita-image-store.s3.amazonaws.com/0/278959/c344c197-4816-22f5-07e7-867b3220c692.png)


また、QiitaDeckを初めて利用するユーザーが、操作方法や機能についての「わからない」を少しでも減らす為に、**初めてサイトに訪れた方には"機能説明チュートリアル"を表示する**ようにもしました。

##振り返ってみて
初めてのWebサービス開発でしたが、おおよそ２ヶ月ほどでリリースまで辿り着くことができて、とても安堵しております。

今回の開発で、OAuth周りの知識や、ユーザー情報やカラム状態の保存などの処理について、Ruby on Railsについて、インフラ周りについてなど、基礎的な知識から応用的な知識まで幅広く学ぶことができました。

最初からわからないことが多かった分、バグや想定外の挙動が発生したときの対処に大変苦労しましたが、その分技術力だけでなく、デバッグ能力や検索能力も向上させることが出来ました。
###おまけ
Qiitaの投稿をリアルタイムでウォッチできるエンジニアのあなたのためのサービス「QiitaDeck」
:link:　[QiitaDeck - もっとQiitaで情報収集！](https://qiitadeck.com/)

##参考記事・サイト一覧
:link:[ ドラッグ＆ドロップで要素を並び替えることができるSortable.js](https://spyweb.media/2017/11/02/js-drag-and-drop-sortable-plugin/)

:link:[ 【jQueryUIを使わずにドラッグ＆ドロップを実装したい】Javascriptライブラリ「Sortable」を使ってみた](https://qiita.com/AVELWP/items/536c797a63c081cf7bc0)

:link:[ 【jQuery】超簡単jQueryスライダー［bxSlider］の使い方。](https://on-ze.com/archives/1658)

非常に参考になりました。この場を借りて深く感謝を申し上げます。ありがとうございました！！