LoginSignup
3
2

More than 5 years have passed since last update.

うさぎを飼ってWebアプリをつくった話

Last updated at Posted at 2018-12-02
1 / 7

概要

  • うさぎ飼い始めました
  • その中で出てきたニーズをWebアプリにしました

コード

  • https://github.com/junara/usareco
  • https://usareco.herokuapp.com で活用しています。しかし、登録されたユーザー(自分)以外だとエラーになりますのでリンクにしていません。

うさぎのペレット量の計算は面倒くさい

  • 体重 * XX %で決まる
  • XXは体重と月齢の関数で算出
  • 毎日計算するの面倒くさい

やりたいこと

  • 体重量ったらペレット量がすぐ知りたい

作るもの

  • 体重を聞いて、ペレット量を返すBOT

作ったもの

image.png

全体像

image.png

image.png

image.png


動作動画

  • (うさぎの誕生日は登録してあります)
  • 1000と投稿した例
    • 我が子 BOTがペレット量50.0gと教えてくれます
  • (おまけ)投稿した内容は今日の記録としてDBに蓄積されます Image from Gyazo

Slack連携のところ

  • 参考

  • Slack Event API

    • slack event apiでアプリを作っておく
      • Event subscriptions:
        • Request URL: /api/rabbits/:token/slack:token はrabbit毎に固有のtoken。)作っておく
        • Subscribe to Workspace Events: message.channels
        • Bot User: 適当な名前で作る。今回は usagi
        • Incoming Webhooks: 特定のチャンネル(今回は #rabbit )にBOTがレスポンスを返すためのwebhook URLを取得します。このURLをDBに入れておく(rabbit.slack_webhook_url)。
    • 上記アプリを管理画面からslackにインストールしておく
  • Rails側は上記postを受けて以下を実行

    • メッセージ中の数字を今日の体重として保存
    • 体重からペレット量を計算
    • Incoming webhookでslackへ投稿
      • (ポイント)Botによるslackへの投稿で発火しないように @body['event']['subtype'] == 'bot_message' の場合はslack通知をしないようにする
    • slackへの投稿はgem slack-notifierをつかいました
app/controllers/api/rabbits_controller.rb
class Api::RabbitsController < Api::ApplicationController
  protect_from_forgery except: [:slack]

  def slack
    rabbit = Rabbit.find_by(token: params[:token])
    return unless rabbit.present?

    body = JSON.parse(request.body.read)
    case body['type']
    when 'url_verification'
      render json: body
    when 'event_callback'
      unless from_bot?(body) # BOTが無限に会話しないようにユーザーからの発言のみに応答するため
        num = body['event']['text'].match(/\d+/).present? ? body['event']['text'].match(/\d+/)[0] : nil # 数値を正規表現で取得
        feeding = rabbit.feeding(date: Time.current) # 今日の日付
        if feeding.body_weight.present? # newの場合
          feeding.body_weight.update(gram: num)
        else # updateの場合
          feeding.builds
          feeding.body_weight.assign_attributes(gram: num, scaled_at: Time.current)
          feeding.body_weight.save
        end
        if rabbit.slack_webhook_url # slackへ投稿。予めwebhook_urlを取得してDBに入れておく。
          notifier = Slack::Notifier.new(rabbit.slack_webhook_url)
          message = "ぼくの体重は#{feeding.body_weight.gram}g。ペレットは1日#{rabbit.ideal_pellet_gram&.round(1)}gでおねがいね![くわしくはこちら](#{root_url}) 。"
          notifier.ping(message)
        end
      end
      head :ok
    end
  end

  private

  def from_bot?(body)
    body['event']['subtype'] == 'bot_message'
  end
end

ペレット量の計算はこちら。

app/models/rabbit.rb
  def ideal_pellet_gram
    return unless latest_body_weight
    latest_body_weight_gram = latest_body_weight.gram
    coefficient = if latest_body_weight_gram < 400
                    0.07
                  elsif age_of_month <= 6
                    0.05
                  elsif age_of_year < 5
                    0.02
                  elsif age_of_year >= 5
                    0.01
                  end
    latest_body_weight_gram * coefficient
  end

おまけ(Webの画面)

  • 投稿された体重はDBに蓄積
  • 我が子の成長グラフでみて☺️
  • chartkickでグラフ描画
    • gem 'chartkick' image.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2