Madogiwa Blog

主に技術系の学習メモに使っていきます。

MeCabとRubyで形態素解析をやってみる👩‍🔬

今回は、MeCabを使って形態素解析を行ってみたので、やり方とかをメモしておきます✍

MeCabとは?

MeCab京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクトを通じて開発されたオープンソース 形態素解析エンジンです。 言語, 辞書,コーパスに依存しない汎用的な設計を 基本方針としています。

MeCab: Yet Another Part-of-Speech and Morphological Analyzer

MeCabのインストール

インストールの方法は、公式サイトをご確認ください。

http://taku910.github.io/mecab/#install

※公式サイトに書いてないですが、apt-gethomebrewを使ってもインストール出来るようです。

私はMeCabrailsをインストールするDockerfileを作って構築しました👀

gist.github.com

MeCabの使い方

mecabコマンドを実行するとMeCabが起動し形態素解析を行うことが出来ます🙌

$ mecab
鳴かぬなら鳴くまで待とうホトトギス
鳴か  動詞,自立,*,*,五段・カ行イ音便,未然形,鳴く,ナカ,ナカ
ぬ 助動詞,*,*,*,特殊・ヌ,基本形,ぬ,ヌ,ヌ
なら  助動詞,*,*,*,特殊・ダ,仮定形,だ,ナラ,ナラ
鳴く  動詞,自立,*,*,五段・カ行イ音便,基本形,鳴く,ナク,ナク
まで  助詞,副助詞,*,*,*,*,まで,マデ,マデ
待と  動詞,自立,*,*,五段・タ行,未然ウ接続,待つ,マト,マト
う 助動詞,*,*,*,不変化型,基本形,う,ウ,ウ
ホトトギス 名詞,一般,*,*,*,*,ホトトギス,ホトトギス,ホトトギス
EOS

RubyMecabを使う

mecabを扱うgemがあるので、Gemfileに追記してbundle installします。

gem 'mecab'

MeCab::Tagger.new.parseに文字列を渡すをmecab実行時と同様に形態素解析を行うことが出来ます。

irb(main):003:0> puts MeCab::Tagger.new.parse "鳴かぬなら鳴かせてみようホトトギス"
鳴か  動詞,自立,*,*,五段・カ行イ音便,未然形,鳴く,ナカ,ナカ
ぬ 助動詞,*,*,*,特殊・ヌ,基本形,ぬ,ヌ,ヌ
なら  助動詞,*,*,*,特殊・ダ,仮定形,だ,ナラ,ナラ
鳴かせ   動詞,自立,*,*,一段,連用形,鳴かせる,ナカセ,ナカセ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
みよ  動詞,非自立,*,*,一段,未然ウ接続,みる,ミヨ,ミヨ
う 助動詞,*,*,*,不変化型,基本形,う,ウ,ウ
ホトトギス 名詞,一般,*,*,*,*,ホトトギス,ホトトギス,ホトトギス
EOS
=> nil

今回は、下記のようなClassを使って扱いやすいような形で取得できるようにしてみました👀

class MecabClient
  attr_reader :text, :parsed_text, :words

  def initialize(text)
    @text = text
    parse
  end

  def parse
    @parsed_text = MeCab::Tagger.new.parse @text
    @words = parsed_text_rows.map { |row| build_word(row) }
    @parsed_text
  end

  private

  def parsed_text_rows
    rows = @parsed_text.split("\n")
    rows[0...(rows.length - 1)]
  end

  def build_word(row)
    text = row.split("\t")[0]
    properties = row.split("\t")[1].split(',')
    Word.new(
      text: text,
      category1: properties[0],
      category2: properties[1],
      category3: properties[2]
    )
  end

  class Word
    attr_reader :text, :category1, :category2, :category3

    def initialize(text: nil, category1: nil, category2: nil, category3: nil)
      @text = text
      @category1 = category1
      @category2 = category2
      @category3 = category3
    end

    def noun?
      @category1 == "名詞"
    end

    def number?
      @category2 == ''
    end
  end
end

こんな感じで使えます🙌

irb(main):010:0> pp keyword = MecabClient.new("鳴かぬなら鳴かせてみようホトトギス")
#<MecabClient:0x00005617509423f8
 @parsed_text=
  "鳴か\t動詞,自立,*,*,五段・カ行イ音便,未然形,鳴く,ナカ,ナカ\n" +
  "\t助動詞,*,*,*,特殊・ヌ,基本形,ぬ,ヌ,ヌ\n" +
  "なら\t助動詞,*,*,*,特殊・ダ,仮定形,だ,ナラ,ナラ\n" +
  "鳴かせ\t動詞,自立,*,*,一段,連用形,鳴かせる,ナカセ,ナカセ\n" +
  "\t助詞,接続助詞,*,*,*,*,て,テ,テ\n" +
  "みよ\t動詞,非自立,*,*,一段,未然ウ接続,みる,ミヨ,ミヨ\n" +
  "\t助動詞,*,*,*,不変化型,基本形,う,ウ,ウ\n" +
  "ホトトギス\t名詞,一般,*,*,*,*,ホトトギス,ホトトギス,ホトトギス\n" +
  "EOS\n",
 @text="鳴かぬなら鳴かせてみようホトトギス",
 @words=
  [#<MecabClient::Word:0x0000561750941db8
    @category1="動詞",
    @category2="自立",
    @category3="*",
    @word="鳴か">,
   #<MecabClient::Word:0x0000561750941a20
    @category1="助動詞",
    @category2="*",
    @category3="*",
    @word="">,
   #<MecabClient::Word:0x0000561750941688
    @category1="助動詞",
    @category2="*",
    @category3="*",
    @word="なら">,
   #<MecabClient::Word:0x00005617509412f0
    @category1="動詞",
    @category2="自立",
    @category3="*",
    @word="鳴かせ">,
   #<MecabClient::Word:0x0000561750940f58
    @category1="助詞",
    @category2="接続助詞",
    @category3="*",
    @word="">,
   #<MecabClient::Word:0x0000561750940bc0
    @category1="動詞",
    @category2="非自立",
    @category3="*",
    @word="みよ">,
   #<MecabClient::Word:0x0000561750940828
    @category1="助動詞",
    @category2="*",
    @category3="*",
    @word="">,
   #<MecabClient::Word:0x0000561750940490
    @category1="名詞",
    @category2="一般",
    @category3="*",
    @word="ホトトギス">]>

おわりに

今回は、MeCabrubyを使って形態素解析を行う方法についてまとめてみました。 形態素解析と聞くと難しい感じがしますが、ツールを使うと意外と簡単に出来ますね🙏

Vue.js + marked.js + highlight.jsを使ってシンタックスハイライト機能付きマークダウンエディタを作ってみたのでMEMO

最近、Vue.jsとmarked.jsとhighlight.jsを使ってマークダウンエディタを作ったので、使い方等をBlogにまとめておこうと思います🙇

はじめに

まず作ろうとしているのは、こんな感じです。

f:id:madogiwa0124:20190103202247p:plain

普通のコードシンタックスハイライト機能付きのマークダウンエディタというような形です👀

まずはテンプレートを用意する。

まずは、今回のマークダウンエディタ用のテンプレートを用意します。 入力用のテキストエディタ(#editor)とプレビュー用(#preview)の要素を持つ単一ファイルコンポーネントを下記に記載しました。
また、テキストエディタには入力値をバインドするためにv-modelを記載しています。※スタイルは割愛してます。

<template>
  <form id="post-form">
    <div id="editor">
      <textarea v-model="markdownText">input</textarea>
    </div>
    <div id="preview">
    </div>
  </form>
</template>
<script>
  export default {
    name: 'postForm',
    data: function () {
      return {
        markdownText: ''
      }
    }
  }
</script>

marked.jsを使ってマークダウンテキスト→HTML変換を行う

それでは、marked.jsを使って入力値をHTMLに変換していきます。

https://github.com/markedjs/marked

まずはmarked.jsをインストールしましょう。

$ npm install marked --save

私は上記コマンドで行いましたが、詳しいインストール方法は下記を参考してください。

https://marked.js.org/#/README.md#installation

インストールが終わったらmarked.jsimportします。

import marked from 'marked';

そして下記のcomputedを追加します。markedの引数に変換したい文字列を渡せば、それに応じたHTMLを返してくれます👀

computed: {
  compiledMarkdown: function () {
    return marked(this.markdownText)
  }
},

あとは#previewv-html使ってバインドしてあげればOKです🙌

<div id="preview">
  <div v-html="compiledMarkdown"></div>
</div>

最終的にはこんな感じになります、これでエディタに応じたHTMLがバインドされるようになりました!意外と簡単ですね✨

<template>
  <form id="post-form">
    <div id="editor">
      <textarea v-model="markdownText">input</textarea>
    </div>
    <div id="preview">
      <div v-html="compiledMarkdown"></div>
    </div>
  </form>
</template>
<script>
  import marked from 'marked';

  export default {
    name: 'postForm',
    data: function () {
      return {
        markdownText: ''
      }
    },
    computed: {
      compiledMarkdown: function () {
        return marked(this.markdownText)
      }
    },
  }
</script>

highlight.jsを使ってシンタックスハイライト機能を追加する。

次にhighlight.jsを使ってコードシンタックスハイライト機能を追加していきましょう!

https://highlightjs.org/

まずは先程と同様にhighlight.jsをインストールしましょう!

$ npm install highlight.js --save 

私は上記コマンドで行いましたが、詳しいインストール方法は下記を参考してください。

https://highlightjs.org/usage/

インストールが終わったらhighlightjsimportします。

import hljs from 'highlightjs';

まずは、createdの中でhighlight.jsを使うようにmarkedのオプションを変更します。

created: function () {
  marked.setOptions({
    // code要素にdefaultで付くlangage-を削除
    langPrefix: '',
    // highlightjsを使用したハイライト処理を追加
    highlight: function(code, lang) {
      return hljs.highlightAuto(code, [lang]).value
    }
  });
},

最後にハイライトで使うスタイルシートを読み込みます。私は、github-gist.cssにしましたが、他にも色々あるようなのでお好きなスタイルを使ってみてください👀

<style src='highlightjs/styles/github-gist.css'></style>

最終的には、こんな感じになりました!これでハイライト機能が出来ました🙌

<template>
  <form id="post-form">
    <div id="editor">
      <textarea v-model="markdownText">input</textarea>
    </div>
    <div id="preview">
      <div v-html="compiledMarkdown"></div>
    </div>
  </form>
</template>
<script>
  import marked from 'marked';
  import hljs from 'highlightjs';

  export default {
    name: 'postForm',
    created: function () {
      marked.setOptions({
        langPrefix: '',
        highlight: function(code, lang) {
          return hljs.highlightAuto(code, [lang]).value
        }
      });
    },
    computed: {
      compiledMarkdown: function () {
        return marked(this.markdownText)
      }
    },
    data: function () {
      return {
        markdownText: ''
      }
    }
  }
</script>
<style src='highlightjs/styles/github-gist.css'></style>

おまけ:マークダウンのデザインを調整する

マークダウン用のスタイルを設定するのがめんどくさい人は、公開されているマークダウン用のスタイルがあるみたいなので、それを使ってみるのもありかと思いました!

ちなみに私はライセンスフリーの下記を使ってみました👀

github.com

おわりに

ライブラリを使うと結構簡単にマークダウンエディタが作れるんですね👀マークダウンエディタはシンプルかつ、いろいろ自分のアイデアを組み込めるので、勉強には良さそうな気がしました🤔
ここから色々機能を追加して、フロントエンド関係の知識も身に着けていきたいですね💪

参考

qiita.com

qiita.com

2018年の振り返り

2018年も終わりですね。年末ということで振り返り記事を書いてみる。

今年の振り返り

アウトプット

今年はBLOGを書いたり、ちょっとしたアプリを作ってみたり、初めてOSSにコントリビューションしたりしました👀

BLOG

今年は、1記事 / 2週を目標に学んだことをブログでアウトプットしようと思い、2018年は46記事(週に1回ぐらい)書いてました! 下記が印象深い記事を抜粋したものです✍

madogiwa0124.hatenablog.com

madogiwa0124.hatenablog.com

madogiwa0124.hatenablog.com

madogiwa0124.hatenablog.com

madogiwa0124.hatenablog.com

madogiwa0124.hatenablog.com

OSS

railsrspec-style-guideに、大したことない対応ですがコントリビュートしました🙇‍♂️

github.com

github.com

つくったもの

今年もしょうもないものや、Webサービス的なもの、LINE BOTとかGemとかそこそこ作りましたね👀

github.com

twitter.com

madogiwa0124.hatenablog.com

quiz-quiq.herokuapp.com

madogiwa0124.github.io

今年の目標

去年の目標と振り返り

目標 結果 コメント
誰かに使ってもらえるWebサービスをつくる rails勉強Botはフォロワー15人、sppは676回Downloadされてるみたいなので一応達成😅
ネイティブアプリと連動したWebサービスをつくる ここは出来なかった。。。
本を年間36冊読む 21冊しか読んでなかった😢
SIerからWeb系に転職する ここは達成!
OSSにコントリビュートする railsrspec-style-guideにコントリビュート🎉
スカイダイビング 出来なかった。。。

目標6個に対して達成3つ、未達3つということでそこそこだったけど、 今年は転職したりハワイ行ったりといろいろ出来てよかったなと🙂

今年の目標

目標 説明
web design系の本を3冊は読む 目的を持った読書目標にしようかなと、デザインも勉強したいので👩‍🎨
アプリを作るだけじゃなくて、ちゃんと運用してみる 作るだけじゃなくて、GAとか使って分析とか運用もやってみようかなと👀
rubyjavascript以外の言語に手を出す goとかelixirがちょっと気になっているので💻
勉強会で登壇する 話せることがあれば自社イベントとか、なんかしらの小さな勉強会で登壇にも挑戦してみれたら👩‍🏫
Webサービスを作るだけじゃなくて、ちゃんと運用してみる GAとかの使い方も覚えたいなと👩‍🔬

おわりに

今年は、Web系企業に転職したりOSSにコントリビュートしたり、エンジニアとしての第一歩を踏み出せた一年だったなと。
あっという間だったけど、良い一年だったなと思います。来年は、ただ作るだけじゃなくて、デザインを工夫したり、新しい技術を使ったり、運用をきちんとやったりと、そういうところまできちんと出来るようになれると良いなと思います。

それでは、皆さん来年もよろしくお願いいたします🙇‍♂️

良いお年を。

RubyonRails: 検索フォームから値を受け取って、値があれば検索するときの実装を考えてみる🤔

みなさん、こんばんは。まどぎわです。
今回は検索処理で値があるときだけ絞り込みを行うときにどうやって実装するのが良いのかなと、すこし考えたので検討過程をメモしておきます。

はじめに

今回は、下記のような前提で検索処理を実装することを想定してます。

  • 検索対象はPost、Postにはタイトルと本文がある。
  • Postにはタグが複数紐付いている。タグは、acts-as-taggable-onで実装されている。
  • 検索条件には、キーワード(タイトルの部分一致)とタグがある。
  • それぞれの検索条件が指定されていれば条件で絞り込みを行い、指定されていなければ検索処理を行わない。

まずは何も考えず実装してみる(かなり良くない)

なにも考えず実装すると下記のような感じになりますかね(;・∀・)
自分で書いといてあれですが、ごちゃごちゃしていて辛い・・・。

class PostsController
  def index
    @posts = if search_params[:keyword].present? && search_params[:tag].present?
      Post.where('title LIKE ?', "%#{search_params[:keyword]}%").tagged_with(search_params[:tag])
    elsif search_params[:keyword].present?
      Post.where('title LIKE ?', "%#{search_params[:keyword]}%")
    elsif search_params[:tag].present?
      Post.tagged_with(search_params[:tag])
    else
      Post.all
    end
  end
  
  def search_params
    params.require(:search).permit(:keyword, :tag)
  end
end

とりあえず検索処理をModelに移してみる(あまり良くない)

Controllerはきれいになり、先程よりは良くなりましたが、ごちゃごちゃした部分がModelに移動しただけで根本的な問題は解決してないですね・・・。

class PostsController
  def index
    @posts = params[:search] ? Post.search(search_params) : Post.all
  end
  
  def search_params
    params.require(:search).permit(:keyword, :tag)
  end
end

class Post
  scope :search, ->(params) {
    if params[:keyword].present? && params[:tag].present?
      where('title LIKE ?', "%#{params[:keyword]}%").tagged_with(params[:tag])
    elsif params[:keyword].present?
      where('title LIKE ?', "%#{params[:keyword]}%")
    elsif params[:tag].present?
      tagged_with(search_params[:tag])
    else
      all
    end
  }
end

とりあえずModelの検索ロジックをリファクタリングしてみる(うーん)

さっきよりは断然良さそうですが、最初にallで取得しているところとか、毎回変数に入れているところに、少し違和感を感じますね(;・∀・)
※また最初、この書き方だとallwheretagged_withSQLが発行されてしまい非効率だと思ってたんですが、ちゃんと1回のSQLで取得出来るみたいですね、ActiveRecordすごい🙄

class PostsController
  def index
    @posts = params[:search] ? Post.search(search_params) : Post.all
  end
  
  def search_params
    params.require(:search).permit(:keyword, :tag)
  end
end

class Post
  scope :search, ->(params) {
    posts = all
    posts = posts.where('title LIKE ?', "%#{params[:keyword]}%") if params[:keyword].present?
    posts = posts.tagged_with(params[:tag]) if params[:tag].present?
    posts
  }
end

検索条件ごとにscopeを用意して個別に検索ロジックを実装してみる(良さそう)

今回は、これが良いんじゃないかと思ってるんですが、検索条件別にscopeを用意してあげて、その中で検索条件の有無でallを返すか絞り込みを行った結果を返すか分岐を行っています。
この方法であれば、メソッドチェーンを使って条件を適用出来るため分かりやすい、個別で検索条件を使うときに便利かなと思ったんですが、どうでしょうか?👀

class PostsController
  def index
    @posts = params[:search] ? Post.search(search_params) : Post.all
  end
  
  def search_params
    params.require(:search).permit(:keyword, :tag)
  end
end

class Post
  scope :search, ->(params) {
    search_by_keyword(params[:keyword]).search_by_tag(params[:tag])
  }
  scope :search_by_keyword, ->(keyword) {
    return all if keyword.blank?
    where('title LIKE ?', "%#{keyword}%")
  }
  scope :search_by_tag, ->(tag) {
    return all if tag.blank?
    tagged_with(tag)
  }
end

おわりに

今回は検索ロジックについて、ちょっと考えてみました。
Railsの良い感じの既存メソッドを使って、これよりも良い実装も全然あるような気もするので教えてください(;・∀・)

minimagickで生成した画像をDBに保存したときに`ArgumentError (invalid byte sequence in UTF-8)`が発生したときの対処法

minimagickを最近ちょっと使っているのですが、合成した画像を保存する際に、めちゃめちゃハマったので対応方法をメモしておきますφ(・

事象

画像に文字を合成してMiniMagick::Imageインスタンスを返すImageBuilder::PostThumbnail.buildの返り値からバイナリ文字列を取得し、保存しようとしたところArgumentError: invalid byte sequence in UTF-8が発生した。

[3] pry(main)> p.thumbnail = ImageBuilder::PostThumbnail.build("hoge").tempfile.open.read
[4] pry(main)> p.save
   (0.2ms)  BEGIN
   (0.2ms)  ROLLBACK
ArgumentError: invalid byte sequence in UTF-8

解決策

返り値からバイナリ文字列を取得する際にbinmodeを呼び出してからバイナリ文字列を取得することで解決できました🙌

[6] pry(main)> p.thumbnail = ImageBuilder::PostThumbnail.build("hoge").tempfile.open.binmode.read
[7] pry(main)> p.save
   (0.2ms)  BEGIN
  PostImage Load (4.7ms)  SELECT "post_images".* FROM "post_images" WHERE "post_images"."post_id" = $1  [["post_id", 5]]
  Post Update (2.2ms)  UPDATE "posts" SET "thumbnail" = $1, "updated_at" = $2 WHERE "posts"."id" = $3  [["thumbnail", "<17691 bytes of binary data>"], ["updated_at", "2018-12-01 12:58:39.176813"], ["id", 5]]
  ActsAsTaggableOn::Tagging Load (0.9ms)  SELECT "taggings".* FROM "taggings" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2  [["taggable_id", 5], ["taggable_type", "Post"]]
   (4.7ms)  COMMIT
=> true

binmodeを使うとバイナリモードでファイルを開くことが出来るみたいですね👀
詳細はよくわかってないのですが、今回は画像のバイナリ文字列が取得したかったので、binmodeを使ったほうがよかったみたいです🤔

参考

class IO (Ruby 2.5.0)#binmode

RubyonRails:whereでサブクエリを使って効率よく対象を絞って取得する方法👀

みなさん、こんにちは。まどぎわです(・∀・)
今回は、ちょっと複雑な条件をサブクエリを使って効率よく取得する方法について書こうと思います✍

今回のケース

今回は、「公開中の投稿に紐づくコメントのみを取得する」というケースで考えてみようと思います🤔
前提事項を下記に整理したので、参考までに。

  • 投稿:Post、コメント:Comment
  • 投稿とコメントは 1:N(has_many)の関係
  • 公開済みの投稿はopened: true

対応案を考えてみる

公開中の投稿を変数に入れて紐づくコメントを取得する(いまいち😭)

これはあんまり良くなさそうだなーというのを書いてみました😥
公開中の投稿を取得してpostsに格納したあとに、それに紐づくコメントを取得しています。 これは、コード行数も2行でコメントを取得する際に毎回SQLが発行されしまうため非効率です。。。

$ posts = Post.where(opened: true)
# => (0.7ms)  SELECT "posts"."id" FROM "posts" WHERE "posts"."opened" = "true"
$ comments = posts.map(&:comments)
=> # 公開中の投稿の数だけ、コメントを取得するSQLが発行される・・・。

pluckを使ってみる(スッキリ書けるけど、効率いまいち🤔)

では、ActiveRelation#pluckを使ってみるのはどうでしょうか?🤔
pluckを使って公開中の投稿のidの配列を取得し、コメントを取得条件に渡します。 1行でスッキリ書けて、一見良さそうに見えますが公開中の投稿のidを取得するSQL公開中の投稿に紐づくコメントを取得するSQLの2回、SQLが発行されてしまっています😥

$ PostComment.where(post_id: Post.where(opened: true).pluck(:id))
=> (0.7ms)  SELECT "posts"."id" FROM "posts" WHERE "posts"."opened" = "true"
   PostComment Load (9.9ms)  SELECT "post_comments".* FROM "post_comments" WHERE "post_comments"."post_id" IN ($1, $2, $3, $4)  [["id", 1], ["id", 2], ["id", 3], ["id", 4]]

※👇pluckの詳しい説明はこちら
Active Record クエリインターフェイス #pluck

selectを使う(スッキリ書けて効率よい🙌)

こういうケースは、ActiveRecord:: QueryMethods#selectを使うと、きれいに効率よく書くことが出来ます💡
書き方はpluckのときとほとんど一緒です。selectを使うことによって、公開中の投稿に紐づくコメントを取得するSQLのIN句に公開中の投稿のidを取得するサブクエリが発行されるようになり一回のSQLで取得することが出来ます!スッキリかけて効率的ですね🙌

$ PostComment.where(post_id: Post.where(opened: true).select(:id))
=> PostComment Load (2.2ms)  SELECT "post_comments".* FROM "post_comments" WHERE "post_comments"."post_id" IN (SELECT "posts"."id" FROM "posts" WHERE "posts"."opened" = "true")

※👇selectの詳しい説明はこちら
Active Record クエリインターフェイス #select

おわりに

ActiveRecord:: QueryMethods#selectをwhereで使うとサブクエリを使って効率よくスッキリ目的のレコードを取得することが出来ます🙌
今まで結構書いてしまっていた気もしますが、pluckだと毎回SQLが発行されてしまうので注意ですね👀

railsの勉強のためのTwitterBotをリリースしました📢

f:id:madogiwa0124:20181111222201p:plain

みなさん、こんばんは。まどぎわです(・∀・)
本日、Rails勉強BotというTwitterBotをリリースしました!🎊
railsを勉強している人には役に立つと思うので、この記事で使い方など紹介します📢✨

rails勉強Botとは?

rails勉強Botは、railsのメソッドとGithub上のソースコードへのリンクを投稿するTwitterBotです🐦
現在は、10分に一回ActiveSupportのメソッドについて呟いてくれています📢

twitter.com

rails勉強Botの活用方法

rails勉強botをフォローすると10分に一回タイムラインに、こんな感じで投稿がされます✍

urlのリンクをクリックするとGithub上のソースコードを確認できます🙌 f:id:madogiwa0124:20181111220631g:plain

メソッドと実際のコードを関連付けて知ることで、より深く処理の中身を知ることが出来るんじゃないかなぁと思ってます👀

どうやって作ってるの?

APIモードのrailsとherokuを使って作っています🔨
ソースコードGithub上に公開してますので、よろしければ見てみてください🐾 github.com

そんなに難しいことはしてなくて仕組みとしては、こんな感じです。

  • public_methodsでpublicなmethodの一覧を取得
  • source_locationで該当methodが記載されたファイルとその行番号を取得
  • Github上のURLに合わせて、取得結果を整形
  • TwitterApiに作成したクラスとメソッドとGithub上のURLの文字列を渡す

👇実際に上記を行っているコードです。
rails_study_bot/active_support.rb at master · Madogiwa0124/rails_study_bot · GitHub

そもそものTwitterBotの作り方は、この辺を参考にしてもらえれば🙌

madogiwa0124.hatenablog.com

おわりに

まだActiveSupportのメソッドしか呟けていないのですが、今後はActiveRecordActionView等、対応クラスを増やして行く予定です💪
自分でも使っていますが、なかなか勉強になることも多いのでrails勉強中の方は、使ってみて感想等頂けると嬉しいです😊

PS. TwitterAPIの承認申請めんどくさすぎた😇

twitter.com