ホーム ブログ ページ 25

【Ruby/Rails】Shift_JISなのかUTF-8なのかわからないCSVを開く【CSV】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

よくCSVを読み込む時にファイルのエンコードが違っていて読み込めず例外が発生することが多々あります。そこで例外発生を抑える方法を記述します。

begin~rescueを使用してCSVを開く

例外が起こるたびに次の方法で開いていくスタイル。

def execute
  csv.each do |row|
    .
    .
    .
  end
end

private

def csv
  begin
    @csv = CSV.foreach(file_path)
    @csv.first # UTF-8で開けなかったらここで例外が起こる
    @csv
  rescue
    CSV.new(open(file_path, 'rb:Shift_JIS:UTF-8', undef: :replace)) # Shift_JISのCSVを開く
  end
rescue
  errors.add :base, '開けぬ...'
  raise
end

def file_path
...
end

gitの大文字小文字でハマった話

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

プロジェクトでバージョン管理にgit/GitLabを使っているのですが、そのgitの大文字小文字の扱いに落とし穴があって困った話です。

Gitは大文字小文字の違いを…

Gitはデフォルトでは大文字小文字の違いを無視する設定になっています。
なっているのですが、git mvを使わずにファイルの名前を変えたときは微妙におかしい無視のしかたをします。

今回はUnityエディタ上でImage.png を image.png にrenameしました。
(mvコマンドなどで名前を変えても同じ現象が起こります)

変えた後 git status でどういう状況になっているか確認してみましょう。

new file:   image.png

なんでやねん!!

違いを無視すると言っても Image.png と image.png を同じファイルだと思ってくれるわけではないようです。
これに気づかずにコミットしてpushすると、リポジトリ的には Image.png と image.png 両方存在することになります。

Image.png と image.png が存在するため、他の人が Image.png に対して変更をした場合、その変更は image.png には反映されません。
さらにImage.png と image.png が別のブランチで変更されてマージしようとしたときにさらなる悲劇は起こります。

コ ン フ リ ク ト

仕方ないな…と思ってgit statusで状況を見てみると

nothing to commit, working tree clean

こうなるともうどうしていいのかわかりません。
同じファイルなのか別のファイルなのかはっきりしてほしいです。

gitの外からmvコマンドなどで名前を変えても同じ現象が起こります。
git mvを使った場合、そもそも同じものだと認識されてrenameできません。

fatal: destination exists ...

解決策

なんとかしてマージしよう

こうなったときは問題のファイルを一旦どこかに退避させて消してコミットしてまた戻しましょう。
あるいは一旦まったく違う名前にしてコミットしましょう。

gitの設定を変えよう

Gitはデフォルトでは大文字小文字の違いを無視する設定になっています。

この設定のせいです。
大文字小文字の違いを認識させたい場合は設定を変えましょう。
git config -l で設定を見ると以下のような行があるはずです。

core.ignorecase=true

trueだと大文字小文字の違いを無視します。falseだと違いを認識してくれます。

まとめ

ファイル名変えた程度の変更の場合、手癖でついよく見ずにコミットしがちですが、よくよく確認しましょう。

[参考]
https://qiita.com/sawadashota/items/aa312a3b7e2403448efe

mysql ダンプとリストア

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

mysqlでデータをバックアップするときや、テスト環境のデータをローカル環境にコピーする時にダンプ・リストアを使います。今回は、ダンプ・リストアの方法と実際にやってみて発生した問題と対処方法についてまとめました。

ダンプ

ダンプは、DBのテーブルやデータをsqlファイルに変換します。DBのバックアップなどに使用されます。

DB指定のコマンドは、指定したDBのテーブル全てに対して以下の処理を順番に行います。テーブル指定のコマンドは、指定したDBのテーブルに対して以下の処理を順番に行います。
DB指定:$ mysqldump -u ユーザ名 -p データベース名 > 出力ファイル
テーブル指定:$ mysqldump -u ユーザ名 -p データベース名 テーブル名 > 出力ファイル
1. テーブル削除
2. テーブル作成
3. データ作成

ダンプには、いくつかオプションがあり、オプションを指定することで上記の処理を細かく分けることができます。

-dオプション:$ mysqldump -u ユーザ名 -p データベース名 -d テーブル名 > 出力ファイル
データ作成を行わずに、テーブル作成・削除のみ行います。

-tオプション:$ mysqldump -u ユーザ名 -p データベース名 -t テーブル名 > 出力ファイル
テーブル作成・削除を行わずに、データ作成のみ行います。

参考ページ:https://qiita.com/PlanetMeron/items/3a41e14607a65bc9b60c

リストア

リストアは、ダンプで出力したsqlファイルからテーブルやデータを作成・更新・削除します。

$ mysql -u ユーザ名 -p データベース名 < 出力ファイル

ダンプ・リストアで発生した問題

テスト環境のテーブルをダンプして、ローカル環境にリストアした時に発生した問題
mysql version:5.6.39
エラー内容:ERROR 1118 (42000) at line 394: Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
1行に8126バイト以上のデータをリストアした為に発生した模様。エラーメッセージの通り、ROW_FORMATの設定をすることで解決することができます。

対処方法
/etc/my.cnfファイルに以下の設定を追加する。

innodb_file_per_table
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda

追加後に、mysqlサーバを再起動するとエラーが発生しなくなります。

参考ページ:http://sawara.me/mysql/2219/

マイグレーションでテーブルを作成して、マイグレーション前にダンプしたsqlファイルをリストア後、マイグレーションを実行した時に発生した問題
エラー内容:Mysql2::Error: Table 'テーブル名' already exists ...
リストアによってDBの状態がダンプファイル出力時の状態に戻ったが、マイグレーションで作成されたテーブルは、DBに残ったままなので、マイグレーション実行時に作成する予定のテーブルがすでに存在するとエラーが表示される。

対処方法
対象のテーブルを削除する。

半年で23kg痩せたダイエットでしたこと。

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

たまごです。 ここ半年ばかりダイエットをしています。経過は順調で現在23kg減です。以下、自分がダイエットするうえでやったことをまとめます。

ゴールの設定

半年間で20kg痩せる目標を立てました。無事当初の目標を達成したので、今は25kg減、その次の目標として30kg減を考えています。

マイルストーンの設定

月一でマイルストーンを設定し、目標体重を決めました。最初は落ちやすく体重が減ってくるにつれて減量しにくくなるはずなので、月ごとの目標体重もカーブを描くように設定しました。

具体的には、2ヶ月目までは-5kg、3ヶ月以降は-3kg、7ヶ月目以降は-2kgで目標を立てました。

進捗の記録

デイリーで進捗記録をしました。いわゆるレコーディングダイエットです。記録にはRecStyleというAndroidアプリを利用しました。シンプルで使いやすいダイエットアプリです。

マイルストーンに対して進捗が思わしくない場合は、改善策を打っていきました。また、あまりにも現実的ではない場合、それは当初の計画に無理があるということなので、マイルストーン側を変更する必要があると思います。期間を延ばしたり、目標値を下げたりです。

幸い、ほぼ進捗どおりか前倒しで痩せることができたので、最初に立てた計画はおおよそ妥当だったものと思われます。

定期報告

マイルストーンごとに定期報告することにしました。報告場所はクローズドなダイエットコミュニティです。報告の必要があるので、励みになります。

ダイエット施策

自分がとった施策はシンプルで、下記の施策を時期によって使い分けていきました。

・食べる量を減らす
・糖質量を減らす
・運動量を増やす

最初はとにかく食事制限によるダイエットでしたが、2~3ヶ月目くらいからそれだけではなかなか落ちなくなってきたので、運動を付け加えました。実施した運動は、腹筋・ウォーキング・自転車です。特に腹筋は、体重は落ちなかったとしても、お腹周りが鍛えられれば、それだけですごく痩せて見えるので、やってよかったなと思います。

栄養面のケア

食事制限していると、必須栄養素が不足しがちなので、補うためにサプリメントを常用するようにしました。ビタミン、ミネラルなどです。特にビタミンBは新陳代謝を活発にさせるためには欠かせないので、肉体改造するなら外せない栄養素です。

スキンケア

急激に痩せると、肌がたるみます。体重はすぐ落ちるけれど、皮膚の代謝には数ヶ月~半年程度かかるからです。そのため、急激に痩せると、肌がたるみ、結果老けて見えます。特に顔は顕著です。これを避けるためにスキンケアをする必要があります。

具体的には、

・上述したビタミン類を摂取して皮膚の代謝を早める
・筋肉を鍛え、その筋肉で皮膚のたるみを支える
・マッサージと保水

などです。

以上です。

Slackで便利な機能3つ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

たまごです。 みなさんslack使ってますか。 今日は、個人的にslackで僕が便利だと思っている機能のご紹介です。

ユーザグループ

https://get.slack.help/hc/ja/articles/212906697-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

全体周知をするためにhereやchannelを使う機会があると思いますが、それだと通知スコープが広すぎるケースがあります。複数チームで同チャンネルを使っていて、特定チームにのみ周知したい場合などです。

そういう場合、ユーザグループの作成が便利です。

これは、メールでいうメーリングリストのようなもので、ユーザグループ宛てにメンションを投げると、そのユーザグループに登録されているユーザにだけ通知がとぶというとても便利なものです。

here乱舞ですと、常に通知ランプが灯って、かえってチャンネル確認が滞ったりするものです。宛先範囲を適切に設定することで、必要十分な範囲に発言を届け、必要十分なメッセージのみチェックすることができます。

スレッド

https://get.slack.help/hc/ja/articles/115000769927-%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%81%AB%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E6%8A%95%E7%A8%BF%E3%81%99%E3%82%8B

そして、やはり便利なのがスレッド機能です。

大人数のチャンネルが早いのでなかなか追いづらいですが、スレッドなら話題ごとに集約してくれるので、チャンネルの流れをゆるやかにすることができ、チェックしやすくなります。

なお、無闇にAlso send to #channel-nameでチャンネル全体に返信させるのはあまり好きなやり方ではありません。スレッドの意義が薄れるからです。それなら、スレッド内で対象ユーザ向けにメンションを飛ばした方がスムーズだと思います。

リマインダー

他、強力なリマインダー機能があって、労働時間帯が違うメンバーに出社後にメンションしたい場合などに便利なのですが、リマインダー文法が日本人にとって直管的ではなく、あまり使いこなせていません。

塗りにひと手間加えてイラストの印象を華やかにする【後編】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

引き続き短時間でイラストの印象を華やかにする方法についてまとめました。

はじめに

nocoです。
前回にも引き続き、時間をかけて塗り込まないでもひと手間でイラストを華やかに見せる方法についてご紹介します。
時短と手抜きは紙一重だなと思うのですが、ポジティブな方に捉えていただけましたら幸いです。

効果や背景を入れてイラストを華やかに見せる

模様やテクスチャを入れる

enter image description here
enter image description here
模様やテクスチャを入れるとデザイン的に見せられたり、塗りの密度が高くなることでベースがシンプルな塗りでも見応えが出ます。
オーバーレイや乗算などでサッと乗せるだけで全体の印象が大きく変わるため、つい色々試したくなってしまいます。
過剰な合成は元のイラストの良さを奪ってしまうので、全体ではなく部分的にかけるなど工夫すると良いかもしれません。
 

グロー効果をかける

enter image description here
アニメの仕上げやイラストのテクニックとしてよく使われる効果です。
明るい色の部分を発光させることでふんわりと優しい印象になります。
シンプルな効果ですが、肌に透明感が生まれ人物が活き活きするように感じられます。
 

背景を追加する

enter image description here
塗りとは少し離れますが、元のイラストには一切手を加えず簡単な模様の背景を追加しました。
イラストの全体的な色調の補色にあたる色を入れると失敗しづらく感じます。
キャラクターだけでなく、他の要素でも簡単に印象を華やかにすることができます。

おわりに

前後編合わせて全6パターンご紹介させていただきましたが、いかがだったでしょうか。
どれも5分足らずでできる内容なので、サッとイラストの見栄えを良くしたいときぜひ試してみてください。

塗りにひと手間加えてイラストの印象を華やかにする【前編】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

短時間でイラストの印象を華やかにする方法についてまとめました。

はじめに

nocoです。
たくさんの時間を使ってひとつのイラストを描きたいと思っても時間は限られたものであり、いつもそうできるわけではありません。
そんな時、サッと描いたらくがきでも見栄えよく見せられないかと横着なことを考えたりもします。
なので今回は時間をかけて塗り込まないでもひと手間でイラストを華やかに(それっぽく?)見せるやり方についてご紹介します。

影や光の色に手を入れて華やかに見せる

enter image description here
アニメ塗りの女の子を用意しました。
ベースカラーはそれぞれベタ塗り、影色もグレー統一のシンプルなものです。
こちらのイラストの塗りにひと手間加えて、それぞれの印象の違いを見ていきましょう。
 

ベースカラーに合わせて影色を鮮やかにする

enter image description here
影色に彩度が高めの色を選ぶことで、ぱっと視認できる色数が増え華やかになります。
ベースカラーによって異なる3色を配置しています。
ベースカラーと影色の色相が離れすぎているとちぐはぐな印象になりやすいため、同系色を選ぶと元の印象を壊しません。
 

光と影の部分にオーバーレイのグラデーションを入れる

enter image description here
光部分に黄色、影部分に茶色のグラデーションをオーバーレイでざっくりとかけました。
塗りの一部にグラデーションが入るだけでイラストに空気感と透明感が生まれます。
イラスト全体の色調に合わせたオーバーレイの色を選んであげましょう。
光には明るめの色、影には暗めの色のグラデーションを入れると印象がまとまりやすいです。
 

影に思いきりビビッドカラーを乗せる

enter image description here
影色をビビッドカラーにすると一気にポップなイメージになります。
影色に合わせてベースカラーも色相を青系に振って爽やかなイメージに調整しました。
ビビッドカラーの主張がうるさすぎる場合は影の範囲を整理するとすっきりします。

おわりに

着彩においてありふれたテクニックかもしれませんが、ひとつひとつ分解していくとかなり量が多いことに気が付きました。
次回も引き続きひと手間のパターンをご紹介したいと思います。

Windows SubSystem for Linuxの導入の仕方

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


Windows SubSystem for Linuxの導入について調べました

はじめに

私は業務でmacOSを使っているのですが、プライベートではwindowsを使っています。ふとした瞬間にコマンドラインからいろいろしたい時にwindowsだとLinuxのコマンドが叩けなかったりします。
結構不便に感じていまして、どうにかしてLinuxコマンドが使えないか調べてみました。
するとWindowsがLinuxを仮想化して立てられるようになっていたのでそれを使ってLinuxコマンドを使える環境を構築してみました。

Windows SubSystem for Linux とは?

windows10のAnniversary Updateで追加された機能の一つで、WindowsでLinuxが使えるようになるという機能の事です。
Windows上にLinuxをおいて、それを動かせるようにするもので、これを入れることでLinuxのコマンドなどを使えるようになります。

導入方法

機能の有効化

スタートボタンから「アプリと機能」をクリックして、アプリと機能のウィンドウを開きます。次に右上にある関連設定の所にあるプログラムと機能をクリックしてください。では右の欄にあるwindowsの昨日の有効化または無効化をクリックします。そこでプログラム機能ウィンドウが出てきますので、そこで「Windows Subsystem for Linux」を探してチェックボックスにチェックを入れて「OK」を押してくださいこれでインストールが始まりますので少し待ちましょう。インストールが終わると再起動を求められるので再起動してください。

ストアからのインストール

次にストアからWSLをインストールします。Microsoft StoreからUbuntuを探してきて「入手」ボタンを押します。インストールが始まるので、インストールが終わったらスタート画面にUbuntuがあると思うので、それを起動します。起動するとユーザ設定を求められるので設定してやります。プロンプトに従っていれば間違えはしないと思います。

ここまででLinuxコマンドを使えるようになりました。これでWindowsでもLinuxのコマンドが使えるようになりました。

まとめ

WindowsでLinuxコマンド使いたい時はWSLを入れましょう。

日常生活にSlackを取り入れよう!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ビジネス向けチャットツールSlackは、仕事だけでなく日常生活にも使うことが出来ます。 今回はリマインダー機能について書いていきます。

リマインダー機能

/remindと入力してエンターを押してみましょう。するとヘルプが現れます。

enter image description here

試しに、以下のように入力してみましょう。
/remind me to 爪切り at 7PM today
enter image description here
リマインド成功です!これによりその日の午後7時にSlackから通知が飛んできて、爪切りをしなければならないことを思い出せます。

meのところを@hogeとしたり、#channelとすることで特定の人、チャンネルにリマインドすることが出来ます。

基本的には、/remind (人物・チャンネル) to (タスク) (いつ)という書き方です。

『いつ』の部分に関しては、everydayで毎日を指定したり、every Fridayで毎週金曜日を指定したり、at 9AM every Fridayで毎週金曜日の午前9時を指定したりできます。

enter image description here

要するに、atのあとに時間を、そのあとに曜日や毎日といった指定ができます。

ちなみに私の環境では、atを省いてevery Fridayとだけリマインド登録すると、自動的に午前9時に設定されました。

また、登録したタスクは/remind listで確認が出来ます。

Slackのリマインダー機能は、本来はおそらくミーティングなどの予定をリマインドするために使うのが正しいと思われますが、私は前回の記事で紹介したTrelloを使うまでもないタスクについては、Slackでリマインドするようにしています。

おまけ

/shrugと入力して送信してみましょう。
enter image description here

【Rails】プレビュー機能等作成の際によくつかう小技

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

プレビュー機能って結構考慮する部分が多くて面倒だったりします。のでそこで自分がよく使っていることを紹介します。

よくあるプレビュー機能の作り方

ボタンにパラメーターをつけてアクション内のif文で分けたりする
app/views/products/edit.slim

= form_for @product do |f|
・
・
・
  = f.submit '保存', name: :submit, value: :save
  = button_tag 'プレビュー', name: :submit, value: :preview, formtarget: :_blank

app/controllers/products_controller.rb

def create
  if params[:submit] == 'preview'
    render 'show'
  else
    @product.save
.
.
.
end

def update
  if params[:submit] == 'preview'
.
.
.
end

煩雑すぎる!!
のでアクションを分けましょう。
でもformの向き先は1つなので通常では分けられないです。
が、そこでjavascriptの登場です。

おすすめなプレビュー機能の作り方

app/controllers/products_controller.rb

def preview
.
.
.
end

app/views/products/edit.slim

= form_for @product, html: { id: :product_form } do |f|



= f.submit '保存'
= link_to 'プレビュー', 'javascript:void(0)', id: :preview_button, data: { request_url: preview_product_path(@product)}

app/assets/javascripts/products.coffee
“`
$main_form = $(‘#product_form’)
$preview_button = $(‘#preview_button’)

$preview_button.click ->
original_action = $main_form.attr(‘action’)
$main_form.attr(‘action’, $(this).data(‘request-url’))
$main_form.attr(‘target’, ‘_blank’)
$method = $main_form.find(“input[name=’_method’]”)
$main_form.find(“input[name=’_method’]”).remove()
$main_form.submit()
$main_form.append($method)
$main_form.attr(‘action’, original_action)
$main_form.removeAttr(‘target’)
“`
ボタンを押したときにformの向き先を変えて仕舞えばいいのです!
変えた後は元に戻すのを忘れずに。
この方法はプレビュ−機能以外にも応用できるのでぜひ使ってみてください

Unityのエディタ拡張の話

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Unityのエディタ拡張で自分で作った最高のウィンドウを使いたい話です。

最高のUnity生活を送っていますか?

自分が書いた記事ではないのですが、
【Unity】メニュー項目を増やして君だけの最強のUnityを作ろう!
この記事を読んでしばらくたったことですし、そろそろUnityにより複雑なことをやらせたくなってきた頃ではないでしょうか。
そう…GUIウィンドウを開いてもう少し細かいことをやらせてみたいですね!しましょう。

ということで簡単なチェックボックスとボタンのあるウィンドウを出してみたいと思います。

自分でウィンドウを作ってみよう

ざっくり必要なことは以下のとおりです。

  1. EditorWindow を継承したクラスを作る
  2. 追加したMenuItemで呼び出される関数ではウィンドウを出す処理を書く
  3. OnGUIという関数内でウィンドウができたときのレイアウトをつくる

EditorWindow を継承したクラスを作る

EditorWindow はカスタムしたエディタウィンドウを作るとき親にするクラスです。

https://docs.unity3d.com/jp/540/ScriptReference/EditorWindow.html

継承しましょう!

using UnityEditor;

public class MyCustomEditorWindow : EditorWindow {
}

継承しました。

追加したMenuItemでウィンドウを出す

using UnityEditor;

public class MyCustomEditorWindow : EditorWindow {
    [MenuItem("Edit/OpebMyCustomEditorWindow")]
    public static void Open() {
        GetWindow<MyCustomEditorWindow>(true);
    }
}

MenuItemへの追加の仕方は別の型が書いた記事を参考にしていただくとして、
これでメニューのEdit以下に Open MyCustomEditorWindow という項目が追加され、Openという関数が呼び出されるようになります。

Openの中では
解説が少しややこしいですが、GetWindow でウィンドウが出せます。
一つ目の引数をtrueにすると、今作っているウィンドウが別のウィンドウで出てくるようになります。

さて、ここまでできれば今作っている画面が出るようになっているはずです(まだ中身のない空のウィンドウですが)。

空のウィンドウ

OnGUIを定義してウィンドウのレイアウトをつくる

このエディタにGUI要素を配置していきます。

チェックボックスを置くのは簡単で、UnityEditor GUILayoutのToggleを使います。
以下の例ではcheckBoxIsOn という変数にToggleのオンオフが入っています。

using UnityEditor 
public class MyCustomEditorWindow : EditorWindow {
    // ...

    bool checkboxIsOn = true;

    public void OnGUI(){
        checkboxIsOn = GUILayout.Toggle(checkboxIsOn, "チェックボックスです");
    }
}
チェックボックスのあるウィンドウ

最後にボタンを置いてみましょう。

using UnityEditor 
public class MyCustomEditorWindow : EditorWindow {
    // ...

    public void OnGUI(){
        checkboxIsOn = GUILayout.Toggle(checkboxIsOn, "チェックボックスです");

        if (GUILayout.Button("ボタンの文字")) {
            // ボタンを押したときに呼び出される処理
            Debug.Log(checkboxIsOn);
        }
    }
}

これで押すとToggleの状態を出してくれるようになりました。

完成品1
完成品2

まとめ

GUILayoutには他にも様々なGUI要素があり、項目もさらに増やすことができます。
ぜひ試してみて最高のUnity生活を送ってください!

HelperとJSで文字数カウント機能を作る

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Ruby on Rails でフォームなんかを作る際、テキスト入力部分に「文字数カウント機能」を付けたいと思うことが多々あります。 テキストエリアの右下とかに「0/30」とか付いてて、テキストエリアに入力するとリアルタイムにカウントしてくれるアレです。 JavaScriptで作れるのですが、テキストエリアがたくさんあるフォーム画面などで、 「こっちのフォームは300文字までだけど、その下のフォームは500文字まで入力できる」 などがあると、いちいち作っていると結構ごちゃごちゃしてきてしまいます。 この文字数カウント生成処理を、railsのhelperに全部入れると、けっこう分かりやすかったのでメモがわりの覚え書きです。

設置する文字数カウントの概要
* 「xx(現在の入力文字数) / xx(最大入力文字数)」の形で表示
* 入力文字数が最大文字数を超えた時、入力文字数の色を赤くする
* 各フォームで最大文字数の値はそれぞれ違う


まずviewを見てみます。
例えば「title」「text」という二つのカラムを持つColumnというモデルについて、
それぞれの値を入力するためのフォームを必要最低限の物だけ設置してみます。

<%= form_for(@column, url: url_path) do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :text %>
  <%= f.text_area :text %>
<% end %>

これだとラベルとそれぞれのテキスト入力エリアしかありません。
文字数カウントを設置したい・・ので、helperに作ってもらうことにしましょう。

def countable_field(model_name, model, attribute, maxlength)
    sanitized_model_name = model_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, '_').sub(/_$/, '')
    content_tag(:div, class: 'text_count') do
      len = model.send(attribute).to_s.length
      style = 'color: red;' if len > maxlength
      concat content_tag(:span, len, id: "#{sanitized_model_name}_#{attribute}_len", style: style)
      concat ' / '
      concat content_tag(:span, maxlength, id: "#{sanitized_model_name}_#{attribute}_max")
    end
  end

ちょっとごちゃごちゃしていますが、
countable_field という関数に「モデル名」「モデルインスタンス」「カラム名」「最大長」を渡すと、HTMLソースを作ってくれるようになりました。
現在の入力文字数部分は「モデルカラム_len」、最大文字数部分は「モデルカラム_max」のidが付くように統一してます。
form_forで出来る入力フォームのidにそれぞれ「len」「max」が付く形です。JSで使います。
初期値がある場合を想定して、テキストエリアの内容が既に最大文字数超えていた場合は、赤くするようにしています。

そして、JSで文字数カウント機能を作っておきます。
CoffeeScriptで作ってみたのが以下です。

$ ->
  $('.countable').on 'click keyup blur change paste input onload', ->
    countLength($(this))

countLength = ($field) ->
  len = $field.val().length
  $("##{$field.attr('id')}_len").html(len)
  countMax = Number($("#" + ($field.attr('id')) + "_max").html())
  countDown = countMax - len
  if countDown < 0
    $("##{$field.attr('id')}_len").css
      color: ‘red’
  else
    $("##{$field.attr('id')}_len").css
      color: 'black’

やっていることは「.countable」というクラスが付いたテキスト入力エリアに変更があったら、
「id : モデルカラム_len」のHTMLの中身に入力された文字数の数値を入れて、
「id : モデル
カラム_max」のHTMLの中身の数値より大きければ、文字色を赤くしています。

あとはビューでcountable_fieldを呼び出してあげればいい・・・のですが。

引数が面倒くさい

渡さなければならないのは「モデル名」「モデルインスタンス」「カラム名」「最大長」。
わりといろいろ渡してあげなければいけません。ちょっと面倒です。出来れば二つぐらいに減らしたい。

form_forの中で使いたいので、ActionView::Helpers::FormBuilderのサブクラスを作ってみましょう。

module ActionView
  module Helpers
    class FormBuilder
      def countable_field(method, maxlength)
        @template.countable_field(@object_name, @object, method, maxlength)
      end
    end
  end
end

先程つくったcountable_fieldメソッドを呼ぶだけの関数ですが、引数として渡すのは「カラム名」「最大文字長」だけになりました。
これをviewに仕込むとこんな感じになります。

<%= form_for(@column, url: url_path) do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, class: 'countable' %>
  <%= f.countable_field(:title, 100)%>
  <%= f.label :text %>
  <%= f.text_area :text, class: 'countable' %>
  <%= f.countable_field(:text, 500)%>
<% end %>

viewに足したのは各入力エリアにcountableクラスを追加したのと、countable_fieldを設置しただけですが、これで文字数をカウントしてくれます。
ActionView::Helpers::FormBuilderのサブクラスを作ることの利点としては、引数を減らすことに加え、
他のモデルについても「カラム名」「最大文字長」だけを渡せば流用できます。

また、form_forで出来る入力フォームのidをもとにjsが補足するので、
nested_formなどの動的にフォームが増えたりするものでも、揃えるようにすれば対応が出来ました。

ServiceWorkerを使う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Service Workerは、ブラウザ上でWebページを表示していない時にでも実行できるスクリプトです。 GoogleのPWA(Progressive Web Apps)の実装に不可欠な技術ですが、ブラウザでスマホアプリのようなPush通知を実装したWeb Push機能に必須の機能です。 今回は簡単にServiceWorkerを試してみます。

ServiceWorkerが使えるか確認してみる

対応しているブラウザ: Chrome、Firefox、Opera
対応しているOS: Windows、macOS、Android

現段階では、WindowsのIEやEdge、iOSの全てのブラウザで使うことができません。
日本のシェアを考えるとiOS非対応なのはとてもネック・・・

ちなみに、対応しているブラウザかを調べるには、
navigator.serviceWorker
が定義されているかを確認します。

さて、ブラウザの開発ツールのコンソールから次のコマンドを実行してみます。

対応しているブラウザ(Chrome)だと
enter image description here

ServiceWorkerContainerというオブジェクトを返します。
このオブジェクトはサービスワーカの登録・解除・状態の取得などの機能を提供しています。

対応していないブラウザ(Safari)だと
enter image description here

undefinedが返ってしまいました。ダメだこりゃ。

ServiceWorkerを使うまでの準備

必要なもの

  • ServiceWorkerのJavaScriptスクリプト
  • インストールするためのJavaScriptコードを含んだHTMLページ
  • SSLまたはlocalhostでアクセス可能なWebサーバ

ServiceWorkerの実体

単なるJavaScriptスクリプトですが、
決められたイベントのうち扱いたいものを追加するだけ、というシンプルなものです。

対応している主なイベントは

  • install
  • activate
  • fetch
  • message
  • push

今回は、GlobalFetch.fetch メソッドが呼ばれたときに、コンソールにメッセージを出すというプログラムです。

self.addEventListener("fetch", function(event) {
   console.log("fetchメソッドが呼ばれたよ!");
});

今回はこのファイルを serviceworker.js という名前で保存します。

ServiceWorkerをインストールする

次に、ServiceWorkerをコントロールしたいサイトでインストールします。

ServiceWorkerContainerregister()メソッドを使います。

navigator.serviceWorker.register("serviceworker.js").then(function(registration) {
  console.log("登録されたよ!");
});

これを含んだHTMLファイル(index.html)を置いて、localhostにサーバをたてて試してみましょう。

簡単なwebサーバならば nodejsで動作する node-web-server が便利です。

インストールは

npm install -g node-web-server

で、起動はHTMLのおいてあるディレクトリで

nws

そして起動します。

http://localhost:8080/

enter image description here

無事インストールが完了しました。

ServiceWorkerがインストールされているかは、開発者ツールでも確認できます。

Firefoxの場合は、 ツール>ウェブ開発>Service Worker または about:debugging#workers
Chromeの場合は、 chrome://serviceworker-internals/

enter image description here

ServiceWorkerにイベントを処理してもらう

fetch リクエストのハンドラをかいたので、実際にfetchを呼び出してみます。

navigator.serviceWorker.register("serviceworker.js").then(function(registration) {
  console.log("登録されたよ!");
  fetch("sample.txt");
});

sample.txtは適当に作成してください。

enter image description here

ServiceWorkerが処理していますね。

Unityで作る2Dテクスチャ組込編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Unityの中に2Dイラストを取り込みプレハブを作るまでのアレソレ

こんにちはtokinです。
Unityでは3Dだけでなく2Dゲームも簡単に作れます。しかしイラストは描けてもどのようにUnityに組み込んだらいいのでしょうか。そんなわけで今回は描いたイラストをUnityに入れ簡単なアニメーションをつけるところまでを分けて行いたいと思います。

①テクスチャを作る

enter image description here

②組み込み

enter image description here
enter image description here
enter image description here

最後に

基本的な構造はここまでですが、プレハブはコンポーネントをつけることで更に複雑な設定ができるようになります。当たり判定をつけたりSEをつけたり、また次の記事でお話しするアニメーションをつけたりなどUnityでは様々な設定をつけることが可能です。必要な要素を付け足していき、よりゲームらしいゲームを制作していきましょう。

次の記事「Unityで作る‼︎2Dアニメーション編

macのbashスクリプト上で文字列のcamelizeやunderscoreをしようとしたらperlに頼るのが楽だったこと

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ruby on rails ではコントローラ名やそこで扱われるモデル名やインスタンス変数名の変換を行いたいときなど、文字列にcamelizeメソッドやunderscoreメソッドがある。 同様のことシェルスクリプト上で行おうとして探してみたところ、macのbash上ではperlを呼び出すのが楽だった。

bashでcamelizeやunderscore

rails上での String#camelize, String#underscore の例

str = 'happy_birthday_to_you!'
Str = str.camelize
 => "HappyBirthdayToYou!"
Str.underscore
 => "happy_birthday_to_you!" 
  • 環境 ruby 2.5.0 rails 5.0.6

bashでやってみる

まずはcamelize

sedを使うとできるらしい

str=happy_birthday_to_you!
echo $str | sed -re "s/(^|_)(.)/\U\2/g"
HappyBirthdayToYou!

sedで正規表現を使うことでできる。(redhat, debian)

ところがmac(Darwin)のsedではエラーになる。

str=happy_birthday_to_you!
echo $str | sed -re "s/(^|_)(.)/\U\2/g"
sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]

perlを使えばmacでも動く

str=happy_birthday_to_you!
echo $str | perl -pe ‘s/(|)./uc($&)/ge;s///g’

つづいてunderscore

sed使用版

Str=HappyBirthdayToYou!
echo $Str | sed -r -e 's/^([A-Z])/\L\1\E/' -e 's/([A-Z])/_\L\1\E/g'
happy_birthday_to_you!

macだとやはり同じsedのエラー

perl使用版

Str=HappyBirthdayToYou!
echo $Str | perl -pe 's/(^[A-Z])/lc($&)/ge;s/([A-Z])/_$&/g;s/([A-Z])/lc($&)/ge'
happy_birthday_to_you!

できたこととする。

macのbashスクリプト上で文字列のcamelizeやunderscoreをしようとしたらperlに頼るのが楽だったこと

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ruby on rails ではコントローラ名やそこで扱われるモデル名やインスタンス変数名の変換を行いたいときなど、文字列にcamelizeメソッドやunderscoreメソッドがある。 同様のことシェルスクリプト上で行おうとして探してみたところ、macのbash上ではperlを呼び出すのが楽だった。

bashでcamelizeやunderscore

rails上での String#camelize, String#underscore の例

str = 'happy_birthday_to_you!'
Str = str.camelize
 => "HappyBirthdayToYou!"
Str.underscore
 => "happy_birthday_to_you!" 
  • 環境 ruby 2.5.0 rails 5.0.6

bashでやってみる

まずはcamelize

sedを使うとできるらしい

str=happy_birthday_to_you!
echo $str | sed -re "s/(^|_)(.)/\U\2/g"
HappyBirthdayToYou!

sedで正規表現を使うことでできる。(redhat, debian)

ところがmac(Darwin)のsedではエラーになる。

str=happy_birthday_to_you!
echo $str | sed -re "s/(^|_)(.)/\U\2/g"
sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]

perlを使えばmacでも動く

str=happy_birthday_to_you!
echo $str | perl -pe ‘s/(|)./uc($&)/ge;s///g’

つづいてunderscore

sed使用版

Str=HappyBirthdayToYou!
echo $Str | sed -r -e 's/^([A-Z])/\L\1\E/' -e 's/([A-Z])/_\L\1\E/g'
happy_birthday_to_you!

macだとやはり同じsedのエラー

perl使用版

Str=HappyBirthdayToYou!
echo $Str | perl -pe 's/(^[A-Z])/lc($&)/ge;s/([A-Z])/_$&/g;s/([A-Z])/lc($&)/ge'
happy_birthday_to_you!

できたこととする。

確率について考える ~期待値と実際の確率~

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

多くの人の身近になったガチャやドロップという存在。 それらを支配する確率について今回は考えてみる。 ※現実の福引のような引ける回数に限りがあるものはここでは考えない。

期待値について

 「1%の確率で最高レアが当たるガチャを500回引けば5枚引けそうだ」
というのが期待値である。誰でも頭では分かっているように、その期待値通りの引きになるとは限らない。1枚も引けない人もいれば、20枚引ける人もいるだろう。それでは一体どれだけの確率で最高レアが引けるのだろうか。

実際に引ける確率

 下のグラフは、最高レアが出る確率がpのとき、最高レアが1度でも引ける確率Xがいくつであるかを示している。青色の折れ線の「期待値1」とは、「p×引いた回数x=1」、つまり期待値が1となる回数分ガチャを引くことである。
enter image description here
 グラフを見れば分かる通り、pが小さいほど「1度でも引ける確率」は収束していき、期待値1では約63%、期待値2では約86.5%、期待値3では約95%となる。なんということか、期待値1になるだけガチャを引いても37%の人は引けないのである。

ガチャの天井

 ガチャでときどき見かけるのが「〇〇〇連引いたら好きなもの1つ選んでいいよ」という天井システムである。このグラフに当てはめてみれば、「救済」なのか「天井前提」なのか、透けて見えてくるかもしれない。逆に作り手側なら、考える指標の1つとして役立つグラフになるだろう。

Unityで作る‼︎2Dアニメーション編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Unityの中に取り込んだプレハブにアニメーションをつけるアレソレ

 こんにちはtokinです。
前回作った部屋の窓の外で雪が降っているようにしたいので、雪の結晶が落ちていくアニメーションを付けていきます。
前回の記事はこちら「Unityで作る‼︎2Dテクスチャ組込編

下準備

 アニメーションをつけるためにも設定するための下準備が必要です。まずモーションをつけたいプレハブのスプライトデータにAddComponentからAnimatorを付けます。次にAssetsの下にアニメーションを入れるフォルダを作成し、その中に右クリック→AnimationとAnimatorControllerを作成します。AnimatorContorollerはAnimationを動かすリモコンのようなものでAnimatorはそれをプレハブに繋げる為の組み込み口となります。
enter image description here

 次にAnimatorウィンドウを開いた状態でAnimatorを選択すると中にAnimationを組み込むことができます。ドラッグしてAnimationを繋げるとEntryからオレンジの矢印が飛び出し組み込んだAnimationをさす状態になります。アニメーションは絶え間なく再生し続けてほしいため、組み込んだAnimationを選択しInspectorに表示されるループ部分にチェックを入れましょう。
enter image description here

 ここまでの工程が完了したらヒエラルキーにあるプレハブのAnimatorの中に先ほどのAnimatorContorollerをドロップして組み込みます。これでこの組み込んだスプライトデータのアニメーションを設定することができます。
enter image description here

アニメーションを作る

さて、早速アニメーションをつけていきましょう。
 Animatorを組み込んだデータを選択した状態でAnimationウィンドウを開きましょう。ここで先ほど組み込んだAnimationデータを設定することができます。しかしこの状態ではまだ何も設定することができません。まずAddPropertyを開きます。ここでアニメーションを設定する項目を増やすことができます。
enter image description here

上下に動かす

 試しに雪が上から下に落ちるように設定します。
まず枠部分を図のように設定します。上の枠はフレーム数でアニメーションの尺を表します。アニメーションをゆっくり再生したいときは少々多めに取るなどして徐々に調整していきましょう。Sampleは1コマ何フレームかを設定できます。試しにフレーム数を150に設定しこの中にアニメーションキーを打っていきます。赤いラインを打ちたい箇所に持っていき先ほど増やした項目「Position」のY座標を記入してエンターを押すとキーが打たれます。どんなキーを打てばいいか迷ったときは、スプライトデータのPositionのXYZの文字上を長押ししながらドラッグすると値ごとスプライトデータも動くので動かしながら理想の位置を探していきましょう。
上下に動かすためにはPositionのY座標を変動させることが必要です。0フレーム目のキーを(X-0.25,Y2.97,Z-1)に、150フレーム目のキーを(X-0.25,Y-0.94,Z-1)にします。雪は夜の壁と親子関係にあるため、Z-1で夜の壁より手前に表示されるようになります。これで夜の壁をバックに上から下へ滑らかに落ちていきます。
enter image description here

回転させる

次は雪の結晶を回転させます。回転させるときはAddPropertyからRocationを追加します。
そしてRocationのZ値に0~360の値をくわえキーを打ちます。0フレーム目に(Z0)、150フレーム目に(Z360)を打つとちょうど綺麗に一回転するようになります。途中でZ値の値をずらしたキーを打てば回転に変化をつける事もできます。
enter image description here

横に動かす

最後に雪の結晶を蛇行しながら落とすようにします。先ほどの一直線に落ちていくように設定したキーの間にXを変更させたキーを入れていきます。キーを打ちたいフレームに赤いラインを持って行った状態でスプライトデータの場所を移動させるとそのままアニメーションのPosition部分にも記入されます。
アニメーションは下のCurveからも設定でき、動きの強弱にこだわりたい場合などはこちらの調整もおすすめです。これでアニメーションの完成です。
enter image description here

終わりに

SpriteStudioなど動画作成ソフトで作ったアニメーションを取り込む事も可能ですがUnityで作るとPosition,Scaleの他にカラーなど幅広く調整することができます。Unityでもぜひアニメーション制作を試してみてください。

RailsでOracle~ 導入と文字列の扱いについて

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Ruby on RailsからOracleデータベースを利用する際のtipsについて紹介します

設定について

ActiveRecordでOracleを扱うには
activerecord-oracle_enhanced-adapter
というgemを使います

Gemfileには下記のように記述します

gem 'activerecord-oracle_enhanced-adapter'

config/database.ymlのアダプタの項目に下記のように指定します

default: &default
  adapter: oracle_enhanced

デフォルトではプライマリキーのシーケンスが10000から始まる(!)ようになっているので、他のDBアダプタと同じように1から始まるように変更します (参照: adapter-settings

config/initializers/oracle.rb

ActiveSupport.on_load(:active_record) do
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
    self.default_sequence_start_value = "1 NOCACHE INCREMENT BY 1"
  end
end

文字列の扱いについて

空文字列を検索しづらい件

Rails側でマイグレーション時に string と指定したカラムは、OracleではVARCHAR2型として定義されます。

Oracleに詳しい方には常識ですが、このVARCHAR2型のカラムには
「長さがゼロの文字列(空文字列)はNULLとみなされる」
という他のRDBMSと違う大きな落とし穴があります。

そのため、WHERE条件にVARCHAR2型のカラムを含める場合、カラムの値が ” の行を検索したいとき

SELECT * FROM tbl1 WHERE col1 = '';

こういうSQLを投げると、 WHERE col1 = NULL と解釈されてヒットしません。
Rails側のコードでいうと

str = ""
Tbl.where(col: str)

これがだめで、 str が ” ならば必ず nil に置き換える必要があります。

pry(main)> str = ""
=> ""
pry(main)> Customer.where(name: str).count
   (0.6ms)  SELECT COUNT(*) FROM "CUSTOMERS" WHERE "CUSTOMERS"."NAME" = :a1  [["name", ""]]
=> 0
pry(main)> Customer.where(name: str.presence || nil).count
   (0.7ms)  SELECT COUNT(*) FROM "CUSTOMERS" WHERE "CUSTOMERS"."NAME" IS NULL
=> 1

カラムがVARCHAR2の場合は ” を nil に置き換えてクエリを投げる、くらいのことはアダプタ側でやってほしいですね。

CLOB型のWHERE検索が難しい

Rails側でマイグレーション時に text と指定したカラムは、OracleではCLOB型として定義されます。

SQLレベルではCLOB型の値とVARCHAR2型の値には互換性がなく、暗黙のキャストが行われないという他のRDBMSとは異なる不便な特徴があります。

シングルクオートを使った文字列リテラルはOracleのSQL構文においてVARCHAR2型の値となるため、CLOB型のカラムをWHERE条件に指定しようとすると、SQLエラーになります。

pry(main)> Customer.where(memo: 'hoge').to_a
  Customer Load (2.0ms)  SELECT "CUSTOMERS".* FROM "CUSTOMERS" WHERE "CUSTOMERS"."MEMO" = :a1  [["memo", #<OCI8::CLOB:0x00558008772008>]]
ActiveRecord::StatementInvalid: OCIError: ORA-00932: データ型が一致しません: -が予想されましたがCLOBです。: SELECT "CUSTOMERS".* FROM "CUSTOMERS" WHERE "CUSTOMERS"."MEMO" = :a1

試行錯誤の末、こういう式で通るようになりましたが、当然ながらインデックスは効きません。

pry(main)> Customer.where('DBMS_LOB.SUBSTR(memo,1000,1) = ?', 'hoge').to_a
  Customer Load (5.5ms)  SELECT "CUSTOMERS".* FROM "CUSTOMERS" WHERE (dbms_lob.substr(memo, 1000, 1) = 'hoge')
=> [#<Customer:0x0055800a7de210 (後略

まとめ

RailsからOracleデータベースを利用する場合、文字列の扱いなど他のRDBMSにはない特殊な特性を把握して、注意しながらコーディングしていく必要があります。
「こう書けば普通に動くだろう」という予断を置かず、実際にこまめに実験して想定通りの結果が得られることを確認しながら進めていきましょう。

次回はOracle Textを使った日本語全文検索など、高度なトピックについて触れていく予定です。

日本語URLをデコードすると空白文字の扱いに困った

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。いくたです。

以前、ブログなどの更新情報をキャッチしてtwitterやslackに投稿するボットを作ったのですが、ひとつ問題が生じました。
それは空白文字を含むURLのデコード問題です。

エンコードとデコード、どっちがどっちだっけ?

よく、どっちがどっちか分からなくなるのでおさらいです。

こんにちは。いくたです。
 ↓ エンコード
%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%82%E3%81%84%E3%81%8F%E3%81%9F%E3%81%A7%E3%81%99%E3%80%82
 ↓ デコード
こんにちは。いくたです。

空白文字を含むURLをデコードすると…

日本語URLはそのページの内容が推察できるので好きなのですが、エンコードされていると長い暗号のような見た目になってしまいます。そのため日本語URLが含まれそうな場合には、デコードの処理を積極的にしています。
しかし、空白文字を含むURLをデコードすると少々問題があるようです。

例えば、Dorubyのこの記事のURL(https://doruby.jp/users/kurokawa/entries/番外編 「子供がスマホを持つことについて」)は全角スペース” ”を含むため、日本語のURLにデコードしたしたものをそのままslackに投稿すると…

before.png

このように、スペースのところでURLが途切れてしまっています。このままリンクをクリックすると存在しないページhttps://doruby.jp/users/kurokawa/entries/番外編に飛んでしてしまいます。

自作のボットではRubyのURIモジュールからdecode_www_form_componentメソッドを使ってデコードしています。詳しいメソッドの使い方はリファレンスを参考にしてください。

2.4.1 :001 > require 'uri'
 => true
2.4.1 :002 > URI.decode_www_form_component("%E3%80%80")
 => " "

全角スペースだけをエンコードされた文字に変換

decode_www_form_componentメソッドを使ってデコードするときに全角スペースだけはデコード対象から除外するようにすれば、今回の問題は発生しません。しかし、除外するいい方法が見つからなかったので、デコードした後で全角スペース” ”だけをエンコードされた文字%E3%80%80に置き換えました。
(だいぶ力技なのでもっとスマートな方法があれば教えていただきたいです…)

require 'uri'

url = "https://doruby.jp/users/kurokawa/entries/%E7%95%AA%E5%A4%96%E7%B7%A8%E3%80%80%E3%80%8C%E5%AD%90%E4%BE%9B%E3%81%8C%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%92%E6%8C%81%E3%81%A4%E3%81%93%E3%81%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%80%8D"
decode_url = URI.decode_www_form_component(url)
# => "https://doruby.jp/users/kurokawa/entries/番外編 「子供がスマホを持つことについて」"
safe_url = decode_url.gsub(/ /,"%E3%80%80")
# => "https://doruby.jp/users/kurokawa/entries/番外編%E3%80%80「子供がスマホを持つことについて」"

これで全角スペースのみエンコードされたURLを投稿することができ、正しいリンクで投稿することができました。
https://doruby.jp/users/kurokawa/entries/番外編%E3%80%80「子供がスマホを持つことについて」

after.png

半角スペースとタブ文字もエンコード文字に変換

デコードしたURLが途中で途切れてしまう現象は半角スペース” “やタブ文字”\t”でも現れます。それぞれエンコード文字に置き換えるメソッドを作りました。

require 'uri'

# 全角スペース/半角スペース/タブ文字をエンコード文字に置き換え
def gsub_space(url)
  url.gsub(/ /,"%E3%80%80").gsub(/ /,"%20").gsub(/\t/,"%09")
end

url = "https://doruby.jp/users/yamana/entries/%09-Photoshop%E3%81%AE%E4%BE%BF%E5%88%A9%E6%A9%9F%E8%83%BD%E2%91%A1"
decode_url = URI.decode_www_form_component(url)
# => "https://doruby.jp/users/yamana/entries/\t-Photoshopの便利機能②"
safe_url = gsub_space(decode_url)
# => "https://doruby.jp/users/yamana/entries/%09-Photoshopの便利機能②"
tab.png

一部分だけエンコードされたURLについて

ブラウザによっては一部分だけエンコードされたURLを受け付けないかもしれません。chromeとsafariでは受け付けてくれたので、最近のブラウザなら問題なく処理してくれそうではあります。

そもそも「一部分だけエンコードされたURL is ちょっと気持ち悪い」という意見もあるようです。うーん…確かにちょっと気になるかも…
時間のあるときにslackのIncoming Webhooksの仕様を読み込んでタイトルのテキストリンクとして投稿する方針に転換してもいいかもしれません。

まとめ

今回のような問題があるのでURLをエンコード/デコードをする際は空白文字に気を遣う必要がありそうです。

それでは、今日はこの辺で。
読んでいただき、ありがとうございました。

火を出す能力について考える

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回はファンタジー等でよく出てくる、火を扱う能力について考えてみたいと思います。

火を出す能力の特徴

 ファンタジー等で扱われている、火を出す能力の大まかな特徴は、
・体や体の一部から、または魔法などで火を発生させる
⇒自分が火になるわけではない(※火になる能力もありますね)
・水に弱い(消される、能力が発動しない)
ということになります。

火って何?

 そもそも火とは何か考えます。火は一言でいうと、物が酸素と激しく反応している現象です。詳細には、可燃物が光や熱を放出しながら、急激な酸化反応(酸素と結びつく反応)を起こす現象です。
 可燃物が燃え続ける条件について調べてみますと、
①燃料が燃えるのに十分な温度
②酸素
③次に燃える燃料
の3つが必要であることが分かりました。

火を出すには…

 水によって火が消されてしまう理由は、「水によって急激に熱が奪われることで、燃えるための温度に届かなくなってしまうこと」が原因です。
 物が一度燃え始めると、燃えることによって放出された熱で、次の燃えるために必要な温度に達し、連続して燃え続けられます。つまり、
十分な温度になる→燃える→発熱する→次のものが燃える→…
といったサイクルを繰り返して燃え続けています。
 従って、水に弱い能力者は熱を出すこと自体はできていないことが分かります。
 よって、水弱点の火の能力者が行っていることは、
①燃料を用意し、何らかの方法で発火させる
②燃料を供給し続ける
の2点であることが分かります。

人が火を出すための燃料

 次は人が出せる燃料について考察していきます。私が燃やすと聞いてすぐ思い浮かんだのは「体脂肪」です。調べてみましたところ、体脂肪が持っている特徴は
・体脂肪⇒水2割+脂肪8割
・脂肪1kg=7200kcal
・引火点は約400度程度
cal(カロリー)は1calで1gの水を約1度上昇させる熱の単位ですので、脂肪1kgでは、『0度の水72リットルを100度まで上昇させる熱量』となります。脂肪とはすさまじい熱量を秘めていますね。また、引火点の温度ですが、ライターの火花などは1000度にも達するそうなので、これらを使って引火させれば大丈夫そうです。

人が出せる火のパワーは?

 上記の試算は脂肪1kg当たりの話でした。では、一般的な人ではどのぐらいのパワーになるのでしょうか。「体重60kg、体脂肪率20%」の人の場合、体脂肪の2割は水でしたので、単純な脂肪の量は、
脂肪:60kg×20%×80%=9.6kg
これを全部熱に変換できた場合、実に最大700リットルもの水を沸騰させることが出来る、ということになります。
 あとは、脂肪を自在に体外へ放出&引火させることが出来れば、火使いの仲間入りです。普段はにっくき体脂肪ですが、自在に操れたら強力な能力者に成れそうですね。

おまけ①:水を出す能力について

 火の天敵として君臨する水を出す能力についても考えてみましょう。
 体内の水を利用して放出する場合について考察します。人は体重と比べて2%の重さの水を失うだけで、ひどく喉の渇きを覚えるそうです。さらに、体重の10%以上の水を失うと危険な状態で、死に至る場合もあるそうです。従って、人が放出できるギリギリの水分量が約体重の10%程度となります。
 つまり、体重60kgの人が出せる水は6kg=6リットルということになります。2%程度である、1.2リットル以下までであれば、比較的安全に利用できそうです。脱水症状には十分注意して使用してください。

enter image description here

火と水が戦ったら
前述のとおり、
火:最大700リットルまで沸騰させられるパワー
水:最大6リットル程度の放出
となり、人間同士が戦う上では火の能力の方が圧倒的に強そうですね。

おまけ②:ほかの火の出し方

 人が放出している可燃性のものと言えば、「屁」ではないでしょうか。調べてみましたところ、人が1日に出している屁は、体積にしておよそ1リットル程度であり、そのうち90%は空気中から取り込んだ、酸素や窒素等の気体のようです。
 仮に、残りの1割が全て可燃性ガスの「メタンガス」であるとしましょう。メタンガスは都市ガス等で日常的に用いられているガスの主成分であり、屁にも含まれているようです。
・メタンガスの熱量:9000kcal/m3
・1リットル:0.001m3
人間が出すメタンガス:0.1リットル⇒0.0001m3 ⇒ 900cal
ということで、コップ半杯程度の水100gの温度を9度上昇させることが出来る程度の熱量になります。これで戦うのは厳しそうですね。

終わりに

 今回は現実の人が火を扱う能力者になれる可能性について考えてみました。私はすでに燃料は十分蓄えているので、後は脂肪を自在に操る能力を身につけたいものです。
※放火は犯罪です。火の取り扱いには十分注意してください。

最近人気な記事