wolfmasa's blog

フロンターレとプログラミング関係の話題を、気が向いたときにつぶやくブログです。

なぜZoomばかり使われるのか

コロナの影響で、一般の人までビデオ会議アプリを使うようになった。

  • Zoom
  • Teams
  • Goole Meets
  • WebEx

私の知る限り、これらの選択肢がある中で、一般用途ではZoomの一人勝ちのような気がする。 ( 一般用途とは、IT業界以外で新規に導入するケース)

なぜか

考えられるポイントは、

  1. 報道や口コミによる宣伝効果
  2. 導入の容易さ

の2つのような気がする。

私の周りでも、今までビデオ会議など知らなかった人がコロナの影響で、 急に導入を検討するケースが多い。

とすると、報道などで聞いたことのあるZoomをとりあえず試してみる(比較検討しない)。

あとは、ちょっと試してみて、面倒なくスムーズに使えることが重要で、 その2点のポイントを多くの人が通って、Zoomばかり使われているように思う。

この点で、今Zoomは成功していると思う。


さて、ではこれでZoomは儲かるようになるのか。

おそらく、ユーザの数%なり一定割合が課金することを期待し、ビジネスを設計していると思うし、 主に40分制限が分岐点になり、うまく課金に誘導しようとしている気がする。

その方向性は正しいと思うが、一方であくまでもコロナの影響で暫定的に使う人が多く、 今後もビジネスモデルとして成り立つかどうかは不明だ。

何せ、今使っているユーザの多くは、基本的な機能が簡単に使えれば満足するような層だ。

そうなってくると、徐々に体力勝負(機能は収束し、無料で多くが提供される)になっていき、 まだ規模の大きくないZoomは辛い勝負になっていく。

あるいは、アトラシアンなりFacebookなりが買収し、他ツールとのシナジーを出して勝負する方向になるかもしれない。

新しいIT業界の事例として、今後も目が離せない。

今年の目標

今年の一番の目標は、「転職」とすることにした。

新しいことにチャレンジしたい。

この先のことを考えたら、もっと違う領域に強みを持ちたい。

いろいろな思いがあって、ここ数年多くの方に話を聞いて、実際に応募してみたりしてきたけど、なかなか良いご縁に巡り合うことが出来ない。

業務ではPC上の画像処理プログラミングを10年近くやっていて、これからはさらにモバイルやWeb(サーバサイドなど)にチャレンジしたいと思い、そのような視点で探しているのだけど、なかなか自分を必要としている会社さんは少ないようだ。

今36歳。

自分としてはまだまだこれから成長していくという気持ちは昔と変わらない気でいるけど、あと5年10年後を考えると、もっともっと角度を上げて成長していく必要がある。

そのために今できることは、環境を変えてさらに挑戦し続けること。

うまくいく気が全くしていないけど、今年の目標は転職として、今までのような中途半端な状態ではなく、きちんと自分の将来に向き合っていこうと思う。

Train-Ticket問題をやってみた

はじめに

Railsの資料を漁っていたら、あの伊藤さんがRailsアプリケーション作成問題を公開していたので、10周くらい遅くなったけど、勉強のためにやってみた。

github.com

元々は、meetupでコードレビューをするための題材ということで、シンプルながらもポイントを抑えた良問だと思います。

実際に、meetupの動画は見当たりませんでしたが、後日ほかの方のも含めてコードレビューを別録した動画をアップされていました。

YouTube

YouTube

1つの考え方とはいえ、Railsを書いていく上での考え方が、随所に参考になりました。ありがとうございます!

やってみた

とりあえず小一時間?で全部の問題を解いてみた。

github.com

問題は、チケット(切符)とゲート(改札)と、それをコントロールするコントローラに絞った問題で、オブジェクト指向的な考え方を問いつつ、所々validationなどRailsの記法や考え方が必要になる感じ。

最初は丁寧にやっていて、ある程度正解と近い部分もあったけど、後半は焦ってしまい、あまりちゃんと考えられなかった。

特に、この問題の1つのポイントであるところの、どこでエラーハンドリングをするか?について、あとで振り返るとコードレビューで伊藤さんも指摘されているようにコントローラに責務を持たせる状態に陥ってしまった気がする。

あとは、エラーチェックのまとまりも、もうちょっと整理して設計でできたなと。

その辺が反省。

答え合わせ

最後に、答えを見ながら写経して、反省をしめる。

github.com

Railsって問題を作るのがどうしても大変だけど、とても勉強になりました。

ありがとうございました。

LINE botをRails6で作ってみた

はじめに

LINEのBOT API(厳密にはMessaging API)をHerokuとRailsを使って実装してみました。

ちなみに、Rails6で作ってみましたが、5と特に変わりはありませんでした。webpackerとか一応叩いてみたけど、あまり関係なかったっぽい。。。

developers.line.biz

今更〜という記事を見て、更に今更ですが(苦笑)、こんな手軽に使うRailsもあるのか、という感じで作れたので記録に残しておきます。

準備

  • Railsのインストール
  • herokuのアカウント+CLIツールインストール
  • LINE Developerアカウント作成

LINEのアカウントは、BOTAPIがリリースされた直後に作ったものがありましたが、気づいたらLINE Developerということでサイトも内容も一新されておりました。

f:id:wolfmasa:20191007182118j:plain

今回は参考サイトでも取り上げられているような、話しかけられたら適当に返事をするだけのアプリケーション。

Ruby on Railsの開発

rails new sarabot -d postgresql

が、いきなりポスグレのbundle installがこける!

調べると(よく考えれば当たり前だが)、ローカルサービスを立ち上げる必要があり、macの場合appをインストールするのが手っ取り早いとのことなので、公式HPからappをインストールし、セットアップ。

bundle config build.pg --with-pg-config=/Applications/Postgres.app/Contents/Versions/latest/bin/pg_config
bundle
bin/rails db:create

これでRailsアプリが立ち上がるので、あとは実装。

bin/rails g scaffold Post name:string
bin/rails db:migrate

まず、返答のデータベースとなるPostモデルを作る。返答は、いくつかの決められたパターンは固定で返答し、それ以外はPostsからランダムで返す単純なもの。

class LinebotController < ApplicationController
    require 'line/bot'  # gem 'line-bot-api'
  
    # callbackアクションのCSRFトークン認証を無効
    protect_from_forgery :except => [:callback]
  
    def client
      @client ||= Line::Bot::Client.new { |config|
        config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
        config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
      }
    end
  
    def callback
  
      # Postモデルの中身をランダムで@postに格納する
      @post=Post.offset( rand(Post.count) ).first
      body = request.body.read
  
      signature = request.env['HTTP_X_LINE_SIGNATURE']
      unless client.validate_signature(body, signature)
        head :bad_request
      end
  
      events = client.parse_events_from(body)
  
      events.each { |event|
  
        # event.message['text']でLINEで送られてきた文書を取得
        if event.message['text'].include?("好き")
          response = "いひひ"
        elsif event.message["text"].include?("行ってきます")
          response = "はーい"
        elsif event.message['text'].include?("おはよう")
          response = "うーーーーーーーん。。。(また寝る)"
        elsif event.message['text'].include?("さら")
          response = "さらちゃん!"
        elsif event.message['text'].include?("ママ")
          response = "ママたん!"
        elsif Post.count == 0
            response = event.message['text']
        else
          response = @post.name
        end
        #if文でresponseに送るメッセージを格納
  
        case event
        when Line::Bot::Event::Message
          case event.type
          when Line::Bot::Event::MessageType::Text
            message = {
              type: 'text',
              text: response
            }
            client.reply_message(event['replyToken'], message)
          end
        end
      }
  
      head :ok
    end
  end

ほとんど参考サイトのコピペ(すみません)。。。 コピペしながら、Messaging APIの仕様をなんとなく理解。

難しいのは、実際にherokuにデプロイしてみないと、APIが叩かれた後の確認やデバッグができないこと。

Rails.application.routes.draw do
  resources :posts
  post '/callback' => "linebot#callback"
end

ちなみに、routes.rbはこんな感じ。

動くか心配のまま、herokuにデプロイ。(上のコードは修正済みなので動きます)

heroku login
heroku create
heroku config:set LINE_CHANNEL_SECRET=xxxxx
heroku config:set config:set LINE_CHANNEL_TOKEN=xxxxxx  #(私のはめっちゃ長かった)
git push heroku master
heroku run

herokuのURLが決まったら、/callbackを含めてLINE Developer設定のWebHookに追記。

これで呼び出されるはず、だが最初は動かず、heroku上のデバッグどうするんだ!?となったので、

heroku run rails c #consoleを開く
heroku run rails tail #ログを確認する

こんな感じでできるよう。ローカルとほぼ同等のことができて素晴らしい(これで今回は十分だったのでこれ以上調べてない)

結局、callbackが呼ばれた後に例外で落ちていたのがログから確認できたので、修正して動きました。

めでたしめでたし。

f:id:wolfmasa:20191007184740p:plain

参考

qiita.com

qiita.com

qiita.com

Rails 6にdeviseを入れてみる

認証機能の実装を行う。

使うのは、有名なdevise

github.com

Gemfileにdeviseを追記し、bundle install

特に過去のバージョンから変わったことはなく、すんなりとインストール完了。

んで、実際にdeviseの設定を行っていくが、これが少し手順が多いため、後で軌道修正する力量がない人は、しっかりと説明の手順通りに進めるの吉。

rails g devise:install

deviseのインストールを行うと、初期化やローカライズファイルと共に、手順の説明が表示される。

これを見逃さずに1つ1つ対応していく。

Running via Spring preloader in process 4957 create config/initializers/devise.rb

  create  config/locales/devise.en.yml

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb:

    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

    In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to something in your config/routes.rb. For example:

    root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example:

    <%= notice %>

    <%= alert %>

  4. You can copy Devise views (for customization) to your app by running:

    rails g devise:views

ActionMailerの設定がどこまで有効かわからないけど、rootパスの設定をし、HTMLのヘッダに警告を表示するコンポーネントを配置したら、viewのcreateを行う。これでわかる通り、まずはviewを作り、そのあと実際に認証を管理するUserクラスを作っていく。

$ rails g devise User
Running via Spring preloader in process 5500
      invoke  active_record
      create    db/migrate/20190910094526_add_devise_to_users.rb
      insert    app/models/user.rb
       route  devise_for :users
$ vim db/migrate/20190910094526_add_devise_to_users.rb 
$ rails db:migrate

deviseからUserモデルを作るが、すでに自分はUserモデルを作成済みで、かつemailのカラムも作っていたので、このままではdeviseが作ったmigrateとバッティングしてエラーになってしまう。そのため、add_devise_to_users.rb の中身でemailを追加する行をコメントアウトして実行する。

あとは、認証をして実際に表示するページを

$ rails g controller Pages index show

で作成して、routeの設定をすると完了。

では、認証とは何か。

まず、表示するページ(GETに応答するHTMLのデータ)をブラウザに返す前に、「認証されていること」を条件にしておく。もし認証されていなければ、403などのエラーを返すことを意味する。

次に、「認証」とは一般的の「ユーザ名」と「パスワード」の対であろう。これをサーバに保持しておき、ユーザが入力した値と比較して一致すれば「認証されている」としても良いことになる。ただし、セキュリティの観点から「パスワード」をそのままサーバ上に保存しておくのは好ましくない。例えばDBをハッキングされ、盗まれた場合や、そもそもサーバの管理者が悪意のある誰かだった場合などに、ユーザに不利益となるからだ。(多くの場合ユーザはパスワードを使い回すのでよりリスクが高い)

なので、サーバ上ではパスワードは暗号化して保存する。ここでは、digestと呼ばれるハッシュ値にして保存しておくことで、ユーザが入力した文字列のハッシュ値と、サーバに保存されているハッシュ値との比較をすることで認証が可能となる。

最後に、ステートレスなHTTP通信でステートを管理するセッションを利用する。おそらく、最も簡単な方法としては、認証が成功した場合にセッション情報としてユーザIDをサーバからブラウザに返し、次回以降の接続にはセッション情報にユーザIDを含めてもらうことで、認証されているものとして扱うことができる。

セッションはサーバ上で作るデータなので有効期限が設定でき、有効期間内であれば再度認証をする必要がないが、もしかしたらユーザIDだけでは、ユーザIDを盗まれた場合になりすましなどのリスクもあるような気がする。これには例えばブラウザ側のIPアドレスをセットでセッション管理に紐づけることで、簡単ななりすましは防げるのかもしれない。

セキュリティ的な観点は詳しくないが、ともあれ、基本的な認証の仕組みはこのようなもので、deviseはこれを簡単に実装してくれるライブラリである。

Rails 6にdeviseを入れてみる

認証機能の実装を行う。

使うのは、有名なdevise

github.com

Gemfileにdeviseを追記し、bundle install

特に過去のバージョンから変わったことはなく、すんなりとインストール完了。

んで、実際にdeviseの設定を行っていくが、これが少し手順が多いため、後で軌道修正する力量がない人は、しっかりと説明の手順通りに進めるの吉。

rails g devise:install

deviseのインストールを行うと、初期化やローカライズファイルと共に、手順の説明が表示される。

これを見逃さずに1つ1つ対応していく。

Running via Spring preloader in process 4957 create config/initializers/devise.rb

  create  config/locales/devise.en.yml

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb:

    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

    In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to something in your config/routes.rb. For example:

    root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example:

    <%= notice %>

    <%= alert %>

  4. You can copy Devise views (for customization) to your app by running:

    rails g devise:views

ActionMailerの設定がどこまで有効かわからないけど、rootパスの設定をし、HTMLのヘッダに警告を表示するコンポーネントを配置したら、viewのcreateを行う。これでわかる通り、まずはviewを作り、そのあと実際に認証を管理するUserクラスを作っていく。

$ rails g devise User
Running via Spring preloader in process 5500
      invoke  active_record
      create    db/migrate/20190910094526_add_devise_to_users.rb
      insert    app/models/user.rb
       route  devise_for :users
$ vim db/migrate/20190910094526_add_devise_to_users.rb 
$ rails db:migrate

deviseからUserモデルを作るが、すでに自分はUserモデルを作成済みで、かつemailのカラムも作っていたので、このままではdeviseが作ったmigrateとバッティングしてエラーになってしまう。そのため、add_devise_to_users.rb の中身でemailを追加する行をコメントアウトして実行する。

あとは、認証をして実際に表示するページを

$ rails g controller Pages index show

で作成して、routeの設定をすると完了。

では、認証とは何か。

まず、表示するページ(GETに応答するHTMLのデータ)をブラウザに返す前に、「認証されていること」を条件にしておく。もし認証されていなければ、403などのエラーを返すことを意味する。

次に、「認証」とは一般的の「ユーザ名」と「パスワード」の対であろう。これをサーバに保持しておき、ユーザが入力した値と比較して一致すれば「認証されている」としても良いことになる。ただし、セキュリティの観点から「パスワード」をそのままサーバ上に保存しておくのは好ましくない。例えばDBをハッキングされ、盗まれた場合や、そもそもサーバの管理者が悪意のある誰かだった場合などに、ユーザに不利益となるからだ。(多くの場合ユーザはパスワードを使い回すのでよりリスクが高い)

なので、サーバ上ではパスワードは暗号化して保存する。ここでは、digestと呼ばれるハッシュ値にして保存しておくことで、ユーザが入力した文字列のハッシュ値と、サーバに保存されているハッシュ値との比較をすることで認証が可能となる。

最後に、ステートレスなHTTP通信でステートを管理するセッションを利用する。おそらく、最も簡単な方法としては、認証が成功した場合にセッション情報としてユーザIDをサーバからブラウザに返し、次回以降の接続にはセッション情報にユーザIDを含めてもらうことで、認証されているものとして扱うことができる。

セッションはサーバ上で作るデータなので有効期限が設定でき、有効期間内であれば再度認証をする必要がないが、もしかしたらユーザIDだけでは、ユーザIDを盗まれた場合になりすましなどのリスクもあるような気がする。これには例えばブラウザ側のIPアドレスをセットでセッション管理に紐づけることで、簡単ななりすましは防げるのかもしれない。

セキュリティ的な観点は詳しくないが、ともあれ、基本的な認証の仕組みはこのようなもので、deviseはこれを簡単に実装してくれるライブラリである。

Rails 6にdeviseを入れてみる

認証機能の実装を行う。

使うのは、有名なdevise

github.com

Gemfileにdeviseを追記し、bundle install

特に過去のバージョンから変わったことはなく、すんなりとインストール完了。

んで、実際にdeviseの設定を行っていくが、これが少し手順が多いため、後で軌道修正する力量がない人は、しっかりと説明の手順通りに進めるの吉。

rails g devise:install

deviseのインストールを行うと、初期化やローカライズファイルと共に、手順の説明が表示される。

これを見逃さずに1つ1つ対応していく。

Running via Spring preloader in process 4957 create config/initializers/devise.rb

  create  config/locales/devise.en.yml

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb:

    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

    In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to something in your config/routes.rb. For example:

    root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example:

    <%= notice %>

    <%= alert %>

  4. You can copy Devise views (for customization) to your app by running:

    rails g devise:views

ActionMailerの設定がどこまで有効かわからないけど、rootパスの設定をし、HTMLのヘッダに警告を表示するコンポーネントを配置したら、viewのcreateを行う。これでわかる通り、まずはviewを作り、そのあと実際に認証を管理するUserクラスを作っていく。

$ rails g devise User
Running via Spring preloader in process 5500
      invoke  active_record
      create    db/migrate/20190910094526_add_devise_to_users.rb
      insert    app/models/user.rb
       route  devise_for :users
$ vim db/migrate/20190910094526_add_devise_to_users.rb 
$ rails db:migrate

deviseからUserモデルを作るが、すでに自分はUserモデルを作成済みで、かつemailのカラムも作っていたので、このままではdeviseが作ったmigrateとバッティングしてエラーになってしまう。そのため、add_devise_to_users.rb の中身でemailを追加する行をコメントアウトして実行する。

あとは、認証をして実際に表示するページを

$ rails g controller Pages index show

で作成して、routeの設定をすると完了。

では、認証とは何か。

まず、表示するページ(GETに応答するHTMLのデータ)をブラウザに返す前に、「認証されていること」を条件にしておく。もし認証されていなければ、403などのエラーを返すことを意味する。

次に、「認証」とは一般的の「ユーザ名」と「パスワード」の対であろう。これをサーバに保持しておき、ユーザが入力した値と比較して一致すれば「認証されている」としても良いことになる。ただし、セキュリティの観点から「パスワード」をそのままサーバ上に保存しておくのは好ましくない。例えばDBをハッキングされ、盗まれた場合や、そもそもサーバの管理者が悪意のある誰かだった場合などに、ユーザに不利益となるからだ。(多くの場合ユーザはパスワードを使い回すのでよりリスクが高い)

なので、サーバ上ではパスワードは暗号化して保存する。ここでは、digestと呼ばれるハッシュ値にして保存しておくことで、ユーザが入力した文字列のハッシュ値と、サーバに保存されているハッシュ値との比較をすることで認証が可能となる。

最後に、ステートレスなHTTP通信でステートを管理するセッションを利用する。おそらく、最も簡単な方法としては、認証が成功した場合にセッション情報としてユーザIDをサーバからブラウザに返し、次回以降の接続にはセッション情報にユーザIDを含めてもらうことで、認証されているものとして扱うことができる。

セッションはサーバ上で作るデータなので有効期限が設定でき、有効期間内であれば再度認証をする必要がないが、もしかしたらユーザIDだけでは、ユーザIDを盗まれた場合になりすましなどのリスクもあるような気がする。これには例えばブラウザ側のIPアドレスをセットでセッション管理に紐づけることで、簡単ななりすましは防げるのかもしれない。

セキュリティ的な観点は詳しくないが、ともあれ、基本的な認証の仕組みはこのようなもので、deviseはこれを簡単に実装してくれるライブラリである。