Rubyの::ModuleName(コロンコロン)について

TL;DR

トップレベルの参照を確実にもたせたい時は ::

経緯

Okinawa.rbでRubyのモジュールを読んでいた所 ::ModuleName の様な書き方のモジュールが発見された

cf. https://github.com/intridea/hashie/blob/4070a699b039a1083971f698647d3707df4b03cc/lib/hashie/hash.rb#L14

cf. https://github.com/sisimai/rb-Sisimai/blob/master/lib/sisimai/string.rb#L49

これはどういう意味なんだろうと、はなちんさんやシーマンさん,Twitterでazumakuniyuki に聞いた所トップレベルの宣言の場合は利用するということがわかった。

たとえば以下のようなコードになるようです。

module Hoge
    module String
        p String
        p ::String
    end
end
~/w/R/Sample ❯❯❯ ruby colong.rb
Hoge::String
String

という訳で :: をつけると組み込みAPIなどのトップレベルで定義された物を利用できるようです

Perl入学式で出来るXXなこと

これはPerl入学式春のブログリレー3日目のエントリです。

昨日はPerl入学式校長のid:papixさんのエントリでした。 Perl入学式の基本スタンスである「プログラミング未経験者の方がプログラミングを好きになってもらえる/良いエンジニアとなる」という事を改めて考え直せました。

さて僕からはPerl入学式に参加してみようかなと思う皆さんに向けて,Perl入学式を完走するとできるようになることについて書いていこうかなと思います。

出来ること

母国語が持てる

ここで言う母国語とは、我々が普段会話に使っている日本語ではなくて、プログラミング言語の母国語です。

母国語、つまりbaseとなる考えをPerlで持つことによって多言語の習得がしやすくなります。例えばrubypythonやGoなど…多種多様な言語も「あぁPerlのアレね…」という感じで理解していく事ができます。

これは僕が1番Perl入学式に参加してよかった所で、入学式に初めて参加した当時は「CやJavaPythonを一通り触ったけどどれもあまり書けないぞ…」となっていました。そこでPerl入学式でPerlをしっかり学び、書籍などで勉強するに連れて、Perlで様々な問題を解決出来るようになりました。プログラミングが苦手なあなたにとってはPerlは最適な処方薬となるでしょう。

また、webアプリケーションを作る際のフレームワークでも同じ事が言えると思っていて、比較的薄いフレームワークが多いPerlではwebの根底が理解できると思います。僕も勉強中なのですが…。

やりたいことが簡単になります

Perl入学式で利用しているPerlは別名グルー言語とも言われ、様々な処理と処理の間を併せ持つことが出来る言語です。

プログラマーでない皆さんも大丈夫。Perl入学式卒業生のid:note103 さんのYAPC::Okinawaでのエントリを見るときっとヒントがあると思います。

note103.hateblo.jp

もし何か◯◯な事を自動化とか楽してみたいんだけど…というのがありましたらぜひPerl入学式のslackで聞いてみましょう。きっと力になれるはずです。

エンジニアの方と話す切っ掛けや内容が増える

Perl入学式の運営をしているサポーターの方や各地域pmの方々と、何を話したら良いのか…そもそもそういう集まりに行って良いのか…と思っている方もいるかもしれません。

Perl入学式に参加すると、例えば「リファレンスがよくわからないんですけど…」とか「utf8周りが複雑で…」などの話の切っ掛けを得ることが出来ます。その切っ掛けから、人々が「#わかる」や「こうすればええんやで」みたいな感じで話がつながります。その話をしながら飲むお酒は楽しいので、ぜひ皆さん参加してみましょう。

サポーターに挑戦

Perl入学式はサポーターと呼ばれるボランティアスタッフで運営をしています。サポーターが在籍している committer チャンネルでのやり取りなど、サポーターになってみないと見えない世界もあります。

…個人的にはPerl入学式は懇親会とサポーターに入ってからが本番の様な所もあるので、ぜひ皆さんにはサポーターとして参加していただきたいです。

(Acme)モジュールを作れる

個人的にPerlの中で好きなAcme名前空間ジョークモジュールをPerl入学式卒業レベルでも作ることが出来ます。

実際に僕も作って何本かあげています。CPANに自分のアイコンと名前が出るのは、Acmeモジュールですが嬉しくなるのでぜひ挑戦してみては如何でしょうか。

そして…

そして、Perl入学式一番の強みは、各地のサポーターを始めとするエンジニアコミュニティの一員になれることです。 僕自身もPerlコミュニティの人々に成長させていただき、今沖縄ではPerl入学式の運営としてエイヤッとしています。

Perlは人と人を繋げるグルー言語。次に繋がる人は画面の前のあなたかもしれません。え?繋がるのが怖いって?

大丈夫です。Perlのスローガンでもある「TMTOWTDI(やり方は一つじゃない)」 です。あなたとPerl、そしてプログラミングとの関わり方の一つとしてPerl入学式に参加していただければ幸いです。

そういえば、Perl入学式が地元でないけど、Perl入学式をしてみたいという方、僕や各地のサポーターに言えば何かが始まるかもしれません。やってみませんか?

明日は id:sorehaedamame さんです。お楽しみに!

Seleniumの良い感じの入れ方

Selenium(良い感じにブラウザをプログラムから操作できるやつ)をインストールしたのでメモ

環境

インスコ方法

$brew install selenium-server-standalone
$brew install chromedriver
$brew services start selenium-server-standalone
$brew services start chromedriver

なんか全部brewで出来て簡単

なぜか chromedriver のみgemと競合する可能性があるのでrubyを使う場合は注意 (具体的に言うとパスと優先度の問題でruby gemの方が優先的に参照されて地獄)

Okinawa.pm#6 でPerl1.0にまつわるLTをしました

okinawapm.connpass.com

という訳でLTです

いつも通り飲み会の後半でLTをするというスタイルで、前々日にリバースエンジニアリングをした事を微塵も感じさせないLTが出来たと思います。楽しかった。

内容

おおよそこのリポジトリのPerl1.0を利用した話です。なお大体のコードはPerl5でも動きます。

その後わかった話としてはPerl1.0では連想配列が何故かダイナミックスコープとして設定されており、これは別のファイルをopenしてその結果をevalしたものでも実行可能です。つまり useっぽいのがPerl1.0では出来なくはないです。

続編

ちなみにPart1と書いてある通り続編をする予定です。お楽しみに

LINE変態コンシェルジュのPerl実装を作った

今すぐ登録

f:id:anatofuz:20180312122318p:plain

元ネタ

review-of-my-life.blogspot.jp

構成

という訳で作ったコードはこちらとなっております。 当初Dockerで動かそうとしていたのでレポジトリ名に名残があります。

github.com

今回はPlack + LINE::Bot::API + Werbservice::YDMMの大まかに3つのモジュールを利用して書いています。まさか自分で作ったモジュールを使うことになるとは思ってなかった。

PerlからLINEBotを叩くにはyappoさんが書かれたPerl HackersHubの記事を読めば大体分かる世界観です。

第44回 LINE Messaging APIで作るchatbot―LINE::Bot::APIとngrokでお手軽に!

実際今回作ったwebアプリも、ほぼサンプルコードの助けを得ながらPlackアプリとして書いた感じです。

ちなみにデプロイしている先はHerokuとなっています。当初はDocker imageをpushして動かそうと考えていたのですが、どうにも動かずbuild packを利用しました。

build packは二ヶ月前までメンテが行われている形跡があるものを利用しています。 github.com

挙動

挙動としては「XX」というとXXを人気順で検索しデフォルトで10件返してきます。

「XXをあと10個」というと追加で10件サーチしてきます。

他には「XXを人気で」「XXを日付で」というとソート順が変更されます。

f:id:anatofuz:20180312144441p:plainf:id:anatofuz:20180312144450p:plainf:id:anatofuz:20180312144453j:plain

ちなみに検索でヒットしなかった場合「XXは見つかんなかった…」と返してきます。

HowTo

LINEとの連携は先程のyappoさんの記事を、DMMとの通信は自作モジュールWebService::YDMMのREADMEなどを読んでいただければおおよその雰囲気はわかるかと思います。

今回のBotでは、偉大なる元ネタが1つのみのレスポンスだったのに対しデフォルトで10個のAVリストを返す実装を行っています。 その為carouse方式でメッセージをbuildし、返却しています。

 my $carousel = LINE::Bot::API::Builder::TemplateMessage->new_carousel(
                alt_text => 'this is a dmm videos',
            );

carouse方式の場合 LINE::Bot::API::Builder::TemplateMessage::Column->new() で作成したオブジェクトに対してメソッド経由でプロパティを設定する事でメッセージを作ることが可能です。

今回は画像サムネイル,動画へのリンク,DMM.comへのリンクの合計3種類をプロパティとしてそれぞれ設定しています。 urlが絡んでくるものは add_uri_action() メソッドを利用して追加します。

                my $col = LINE::Bot::API::Builder::TemplateMessage::Column->new(
                    image_url => $image_url,
                    title     => $title,
                    text      => "Please Selecet",
                )->add_uri_action(
                    label   => '動画で致す',
                    uri     => $movie_uri,
                )->add_uri_action(
                    label   => 'DMMで見る',
                    uri     => $item_uri,
                );
                $carousel->add_column($col->build);
            }

あとは手順通り

            my $messages = LINE::Bot::API::Builder::SendMessage->new()->add_template($carousel->build);
            my $res = $bot->reply_message($event->reply_token,$messages->build);
            ... unless $res->is_success; # error handling

などとすれば簡単にsendできます

注意点

WerbService::YDMMは検索モジュールではありますが、対象の動画がサンプルを持っていない場合もあります。 LINE::Bot::API::Builder::TemplateMessage::Columnは何かしらのURLが必須となっているので、無かった場合は飛ばすという処理が必要となってきます。

またこのURLはhttpsじゃないとダメですが、DMMのレスポンスはhttpなので置換する必要となります。

さらにタイトルは40文字以上だとクエリエラーになるため $title = substr($title,0,39); などとしてあげる必要があります。

感想

たまにこういうの作るとやっぱ楽しいね…

沖縄ぬーやが#1 「2017年後期総決算」を開催しました

主催者がエントリを書くのを忘れるという痛恨のミスでしたが開催しました。

okinawa-nuyaga.connpass.com

きっかけ

もともとインターンで京都に行った際に「京都.なんか」的なイベントが有り、それを沖縄でもやりたい!と思いたって始めたイベントです。

…というのはやや後付け設定感があり、どっちかというとieLTが春の新歓LTだけでしたが、前回秋にLT大会を行ったことなどからLT大会がシーズンでも出来るなと思いやりたかった感じです。

またこれはTwitterで知ったのですが、かつて沖縄には「EXTREME HAGO」というイベントがあり後継イベントと化していたようです。

運営

運営に関しては省エネを心がけており、 id:ST_ha1cyonGitHub issueベースで行っていました。

github.com

issueベースで行っていたのはPerl入学式の運営がこのスタイルであった事と、なるべくオープンにして運営したいというお気持ちがあったためです。結果として上手く行った感じがあります。

今回は日程調整と会場調整で苦労したので次回はもう少しスムーズにしたいですね。

開催してみて

開催する前は人が来るか不安でしたが、意外と皆さんに来ていただいて嬉しかったです。またTwitterで結構な方々に認知していただいた感があるので、今後定期的に開催していきたいなどと思いました。

当日来ていただいた皆さんありがとうございました。

あわせて読みたい

沖縄.ぬーやが#1 という名のLT大会に参加した | ゆとりの無いゆとり世代のゆとりを求めるブログ

沖縄ぬーやが でLT発表してきました! - ごはんと飲み物は紙一重

「沖縄.ぬーやが#1 「2017年後期総決算」」に参加した話 - けけずんセルフハッキング

あきおの情報院生生活: 沖縄ぬーやが#1に参加してきた

Google Spreadsheetに新しい行が追加されたらwebhookとしてidobataに通知を飛ばす方法

バイト先ではチャットツールとしてidobataを使っています。idobataではwebhookのbotがかなり簡単に作ることが可能で、あるエンドポイントに対してpostでアクセスをすると発言をするbotを構成することができます。また形式としてHTMLをサポートしており、特定のオプションを付けてエンドポイントを叩くことでHTMLにレンダリングされたメッセージを発言させることが可能です。

今回はあるスプレッドシートの新規書き込みがあるとidobataに通知を送る仕組みを作りたく、アドオンの設定をするよりGASで書いたほうが様々な面で良かった為にGASでおおよそのbotを作成しました。そのメモです。

最終更新行の検知

GASでスプレッドシートを利用する場合、まずActiveになっているシートを取得する必要があります。

const sheet = SpreadsheetApp.getActiveSheet() などとすると保持することが可能です。  なおGASは let が使えず constvar で定義をしていく世界観のようです。 Overview of Google Apps Script

次に最終更新の行と列を取得する必要があります。 列は正直どっちでも良いと思うのですが、行は必須となります。 今回のスプレッドシートは、新規依頼が末尾に積まれていくタイプであるのでgetLastRow() で取得する事が可能です。

function add_new_dojo_notice() {
  const sheet = SpreadsheetApp.getActiveSheet()

  const lastRow = sheet.getLastRow()
  const lastColumn = sheet.getLastColumn();

ここから一行の各セルをhtmlに修正してsendするという作業を行っていきます。 今回は予め params_info という変数にbotの出力用も兼ねて種類を配列形式でいれています。

この getRange() では最初に行、次に列番号を指定し、続いて行数の範囲を指定を行います。 なお最後の2変数は省略する事も可能となっています。 ここでは最終更新の1行の各セルを取りたい為、最後の2つは 1,lastColumn としています。

今回は列のサイズ分 i をインクリメントし、セルを右に移動しながら文字列 send_paramas に追記を行っていきます。

ここで注意する事は getRange() で取得する列番号はスプレッドシートの番号であるため、配列形式のようにインデックスが0スタートではありません。基本的に1スタートです。今回は空入力の場合表示させないなどを記述しています。

  for ( var i = 1; i < params_info.length; i++){

    if (sheet.getRange(lastRow,i,1,lastColumn).getValue() == ""){
        continue;
    }

      send_params += sheet.getRange(lastRow,i,1,lastColumn).getValue()
  }

  notice_to_idobata(send_params);
}

実際に通知を送る部分のコードはこの用に素朴になっています。 先程の send_paramssource に紐付けて送っています。

function notice_to_idobata(message) {
  const idobataURL = "IDOBATA.url"

  const playload =
   {
     "source" : message,
     "format" : "html",
   };

  const options = {
    "method" : "post",
    "payload" : playload,
    "format" : "json",
  };

  UrlFetchApp.fetch(idobataURL, options);
  Logger.log(options);
}

注意するべきなのは、idobataにmessageを送る際、送りたいメッセージは source の対応として送らなければなりません。

またこの際にhtmlで送る場合 playloadformat をhtmlに指定しておく必要があります。 指定しなければ、idobata側でHMLタグをただの文字列として解釈します。

options でtypeの指定も可能ですが、これはidobataに対しては意味が無いです。

トリガーの設定

作成したスクリプトは「編集」から「現在のプロジェクトのトリガー」を選択する事でトリガーを仕掛ける事が可能です。 トリガーにはいくつか種類がありますがこのエントリ公式ドキュメントを見る限り「submit」か「値の変更」で行うと良さそうでした。