shibuso.net

プログラミングとかゲームとか

タグ:開発

最近の私のWindowsでのWeb(Rails)開発環境

2019年01月01日 | タグ: 開発 , Web

明けましておめでとうございます。本年もよろしくお願いいたします。早いもので前回投稿してから丸一年放置してしまいました(苦笑) ありがたいことにまだ検索で訪れてくれる方がいるみたいですし、今年は更新していきたいと思います。

Web開発界隈は私の観測範囲では結構Mac派の方が多いですが、最近Windowsを使い始めたという記事を続けて見かけたので、ずっとWindows環境で開発を続けてきたWindows派の私の環境についてもちょっと書いてみたいと思います。ちなみに今の職場は周りは全員Macです。

以前win-sshfsの記事を書いたりしましたが、最近は使わなくなっています。最近はDockerを使うことが多いですが、この方法はDockerでも単純な仮想環境でもどちらでも対応可能です。加えて言うと、別にWindowsじゃなくてMacでも可能です(笑) ただしIntelliJ IDEAかあるいはRubyMine等のJetBrains製のIDEにあるdeployment機能ありきのものです。類似の機能があれば他のIDEでも対応可能かと思いますが、ご了承くださいm(_ _)m

ちなみに私の現在の開発環境はホストはWindows 10 Proで、ゲストとして仮想環境(VirtualBox)にUbuntu18.04を使っています。更にその上にDockerを動かしていて、そこでRailsを走らせています。

何故マウントしないのか

上でも触れましたが、私は過去にsshfsや、更に前はsambaや仮想環境独自のマウント機能を使ってマウントしたりしてきました。ただそれぞれ問題がありました。共通しているのはディスクアクセスが遅くなることです。それがホスト側で問題になること、ゲスト側で問題になること、両方ありました。

色々悩んだ結果、ソースコードはそれぞれの環境で別々に持った方が速度的に問題なくなるということになったのですが、それはそれで今度はソースコードの不整合が発生することになります。

それを対処するためにrsyncみたいなsync機能があればいいなと考えていたのですが、IntelliJ IDEAが便利なdeployment機能を搭載していてくれたおかげで簡単に実現できました。今回紹介する方法はその機能を使った方法ですが、これも上で書いたとおり類似した機能があれば何でも実現可能です。

現在の大まかな構成

構成

ホスト上とゲスト上両方にソースコードを置くことになるのがこの構成の特徴です。Dockerを使う場合は仮想環境上で動かし、仮想環境上のソースコードを置いたディレクトリをDockerにマウントすることで対応します。Dockerが仮想環境上のファイルを見る分には特にディスクアクセスの速度に問題は起こっていません。コマンドラインから立ち上げる時は-vオプション、docker-compose.ymlで設定する場合はvolumesで設定する感じですね。

まずホストからゲストと繋げるためにSSHが繋げるようにしておきます。これは個人的にSSHを導入するのが一番楽だったり、その他開発する上で便利かと思って使っていますが、FTPを使っても対応可能です。

続いてホストとゲストそれぞれの環境でgit cloneしておきます。その方が改行コードの問題とか起こりづらいです、多分。

その後IntelliJ IDEAのdeployment機能を使います。「Tools > Deployment > Configuration」から設定します。ホスト環境とゲスト環境のそれぞれのコードの置き場を設定すれば、初期設定は完了です。ついでにExcluded Pathsタブでホスト環境の.ideaディレクトリと、ゲスト環境のtmpディレクトリ、logディレクトリを指定しておけば大まかに大丈夫かと思います。

ここまで設定すれば実際deploymentツールを実行することが出来るはずです。実行して問題が無ければ設定成功です。最後に「Tools > Deployment > Automatic Upload (always)」を選択すれば、上書き保存する度に勝手にアップロードされます。多分これだけで設定完了です。便利!簡単!

注意点

上記までで一通り使えるようになったかと思いますが、少し注意点があります。

まず気をつけれなければいけないことは、deployment機能は万能ではないということです。上書き保存時にアップロードしてくれますが、ゲスト側で新規にファイルを作ってもホスト環境にダウンロードしてくれません。rails g等でゲスト側でファイルを作成した後には手動で同期を行う必要があります。私はSettingsのKeymapで「Sync with Deployed to...」を設定して、すぐにdeployメニューを呼び出せるようにしています。

それからホスト側の文字コードや改行コードにも、特にWindowsでは気をつける必要があります。Windows上でテキストファイルを新規作成すると改行コードはCRLFになってしまいます。IDEの設定でLFに設定しておくのが無難で、且つファイル作成はIDEから行うように徹底しておいた方が良いと思います。

あとファイル権限周りは同期に失敗する原因になります。特にDockerを使っていると仮想環境とDockerでユーザが違ったりして、ファイルを新規作成する時に毎回設定する必要があったりします。まぁそこら辺は慣れれば毎回意識して設定出来るかと。ちなみに私は常にホスト側でgit commit, pushするようにしています。

まとめ

私のWindowsと仮想環境を使った開発環境の構成を紹介しましたが、完全に我流の構成です。Windowsと仮想環境を使ってどうやってWeb(Rails)開発が楽に出来るかとあれこれ試行錯誤した結果ではあるものの、これよりも便利に開発できる方法があるかもしれないので、これがベストだと主張するつもりもありません。

Macでもまったく同じことが出来るので、個人の趣味嗜好で環境を選択できれば良いんじゃないかなと思います。アプリと違ってWeb開発はあまりOSに縛られないのが楽なところかと思います。私は以前Macを買って使ってみたものの肌に合わなかったので、今後もしばらくはWindows環境でやっていけたらと思います。

WindowsでVirtualBoxのVMが起動できなくなった

2017年07月09日 | タグ: 開発

他に書きたい事があるけれど、直近で不具合に遭遇したのと解決出来たのでまとめてみます。

Windows10にVirtualBoxを入れて使用していたのですが、何かの拍子でVirtualBox自体が起動できなくなりました。恐らくですがWindows10 Creators Updateが怪しいんじゃないかと思っています。アップデート後にすぐに使っていなかったので確信はないのですが。

そこでひとまずVirtualBoxを最新のもの(5.1.22)に更新してみました。するとVirtualBoxは起動できるようになったのですが、今度は肝心の仮想環境が立ち上がりません。エラーメッセージには「NtCreateFile(\Device\VBoxDrvStub) failed: Unknown Status -626」という表示が。なんのこっちゃって感じです。

検索してみたら2年前のQAがヒットしたりしてたのでWindowsの更新が原因じゃないのか?と悩んだりしましたが、回答としては最新の物で更新したりWindowsを以前のバージョンに戻したり、test buildsというbeta版のようなものを使ってみるというものがありました。そこで5.1.23を入れてみたところ、ちゃんと動いてくれるようになりましたヽ(´ー`)ノ

ちなみに何か変な設定が残るとまずいかなと思ってVirtualBoxは毎回アンインストールしてからインストールし直してました。それと仮想イメージには一切手を触れなかったのでデータとしては何も問題なく使えました。

一時はどうなることかと思いましたが、無事使えたのでホッとしてます。しかしこの症状の原因がWindows10 Creators Updateが原因だとしたら、リリースされてから時間が経ってると思うのでもっと色々被害があってもおかしくないと思うのですが、何か別の原因なのかあるいは環境によるんでしょうかね? 結局問題の原因がわからなかったのが、今後また再発しないかが気になる点です。

2017/07/20 追記
5.1.24がリリースされていたので導入してみたところ、こちらでも問題なく動作しました。

Angular2を利用していると思ったら…

2017年06月15日 | タグ: 開発 , Web

去年の後半に、リリースされたばかりのAngular2を使用してチャット機能を作っていました。チュートリアルとかを一通りこなして実装しましたが、Railsに組み込む部分で四苦八苦したのが印象深いです。

そんなシステムが今朝クラッシュしていました。なんでだろうと思ったらzone.jsが何かコケていると。でも昨日まで動いていて特に手を触れていないのになぜ急に壊れるのか。DBには特に問題はなかったのでこれはもう完全にJS側の問題だろうと思って調べていたところ、RxJSが原因でした。

CDNから読み込んでくる時にバージョン指定していなくて、昨日次期メジャーバージョンアップのalpha版が出されたことでコケたみたいですorz

完全にケアレスミスですね。チュートリアルからコピーしてきた部分でしたが、バージョン指定をしているライブラリもあったので、まぁ気づけよと。RxJSの5系を指定したらまた問題なく動いてくれました。

やれやれこれで一件落着かと思っていたのですが、引き続きsystemjs.config.jsを眺めていたらどうもangular coreの方にもバージョン指定がされていないように見えました。何か嫌な予感が、胸騒ぎがしました…。

 あ…ありのまま 今 起こった事を話すぜ!

『おれはチュートリアルに従いAngular2を動かしていると
思ったらいつのまにかAngular4.2.2になっていた』

な… 何を言ってるのか わからねーと思うが
おれも何をされたのかわからなかった…

頭がどうにかなりそうだった…

見間違いだとか自動アップデートだとか
そんなチャチなもんじゃあ 断じてねえ

もっと恐ろしいものの片鱗を味わったぜ…

いやぁ、本当に設定がザルでした(汗) 幸いな事にAngular4.2.2の今でも(確認した範囲では)問題なく動いてくれていたので、このバージョンでロック。今後こういうことが無いように注意します…。

Let's Encryptを利用してSSLを導入してみた

2017年05月09日 | タグ: 開発

Let's Encryptが正式サービスを開始してからだいぶ経ちますが、ようやくこのブログにも導入してみました。前々から入れよう入れようと思っていたものの、基本サーバとかネットワークに疎いためどうにも億劫で先延ばしにしていました。もうあちこちに導入方法とかまとまっていますし結構簡単だったんですが、Ubuntu16.04でnginxを使っていて、それもパッケージを使って入れるという方法があまり見かけなかったので、備忘録も兼ねて書いてみます。

まず最初に参考にしたのはCertbotの公式ドキュメントです。nginxとUbuntu16.04の組合せについてはこちらのページに書かれていますが、ここでまず一つ問題が。ここに書かれているコマンドは私が見ている現時点では

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot

となっていますが、ここのadd-apt-repositoryがPythonの環境が入っていないと実行できませんでした。そのため先に

$ sudo apt-get install software-properties-common python-software-properties

を実行しました。余談ですが、私は基本aptitudeを使っています。今回はapt-getで書き換えていますが、aptitudeを使っている方は置き換えて考えてください。

さて、上記を一通り実行したらもうCertbotの導入は完了ですね。次はもう証明書の取得です。

$ sudo certbot certonly --webroot -w [ドキュメントルート] -d [ドメイン] --email [メールアドレス]

これで証明書の取得が可能です。ドキュメントルートはRailsだったらRailsルート/publicですね。一つ気をつけたいのは、パッケージで導入した時のコマンドはcertbotだということです。よくQiitaとかでcertbot-autoで書かれたりしてますが、あれは恐らくソースをDLした場合のコマンドです。今回パッケージで導入したから違うわけですね、私はちょっと戸惑いました。

ここまで来ればあとはnginxの設定と証明書の更新の設定です。nginxの設定については

server {
  listen 443 ssl;
  ssl_certificate     /etc/letsencrypt/live/www.example.com/cert.pem;
  ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
}

ここらへんを気をつければ大丈夫なはずです。さくらのナレッジの記事を参考にすると、80でアクセスしてきた場合のリダイレクト処理も書いてあげるとなお親切ですね。

server {
  listen       80 default_server;
  listen       [::]:80 default_server;
  server_name  www.example.com;
  return  301 https://www.example.com$request_uri;
}

そして証明書の更新についてはrootユーザのcronに

0 5 * * 0 certbot renew --post-hook "service nginx restart"

こんな感じで設定しておくと良いかと思います。上記は毎週日曜日の午前5時に証明書の更新を試みる内容になっていますが、どうもこれを実行しても証明書の有効期限が一体期間以上残っていたら更新はしないようになっているようです。

以上が私がLet's EncryptでSSLを導入するまでの大まかな手順でした。

Dockerのマウントが重すぎる件

2017年04月10日 | タグ: 開発

まず前置きとして私は使い慣れているWindows環境が好きで、Macを試してみたものの馴染めずに戻ってきました。しかしWeb開発、それも主にRubyとRailsを使って開発しているためLinux環境は欠かせません。そのため常に仮想環境が必要となりますが、エディタはやはりWindows上で、それもIntelliJ IDEAを使いたいという思いがあります。

そんな私の最近ローカル仮想環境はDockerで構築しています。ただ、Dockerを上手に使っているかと聞かれるとそんなことはなくて、普通のVMのようにSSHだのDBだのあれこれ一つのコンテナに詰め込んでしまっているので、むしろDocker使いの方からは怒られるような使い方をしてしまっている気がします(汗

ただし最近この環境の重さ・遅さに辟易としてきました。何が重いかというと、Dockerでホストのフォルダをマウントしているのですが、その読み込みがとてつもなく遅いときがあるのです。ファイル数も影響しているのか、以前は気にならなかったのですが、最近悪化している気がしていました。

これはどうもDockerというよりもそれを動かしているVirtualBoxのshared folder機能に問題があるみたいです。確かに以前VirtualBox単体で使用していた際も重いと感じたことはありました。またこれはホストOSがWindowsかMacかという点は関係なく重いそうです。それとDockerのフォーラムで結構長いやりとりがされていますが、同じVMというジャンルでもVMwareでもそういう現象が報告されています(人によって程度に違いはあるみたいですが)。

そんな重さに嫌気が差したため、Dockerのマウントを捨てて以前も使っていたSSHFSに変更してみたところ、すこぶる快適になりましたヽ(´ー`)ノ いやぁ、あんなに読み込みが遅かったのが嘘みたいにサクサク動いてくれます。

ただこのSSHFSが万能かというと、そうとは言い切れません。ソースコードはGitで管理しているのですが、ホスト側から管理できなくなりました。正確に書くと、以前はホストOSであるWindowsの環境下にSourceTreeを使って管理していたのですが、今回Docker下にファイルを置くことになったため、どうも不具合が発生して取り扱えません。

IntelliJ IDEAにもGit機能はあるのですが、これも正常に動作しません。むしろindex.lockファイルを生成したままでロックされてしまうため(SourceTreeでも同じ現象が発生しました)、使わないように設定を変更した方が無難です。というわけでソースコードの管理はDocker上でコンソールでGitコマンドを叩いて対応しています。私は以前もコンソールから叩いていたので思い出せば楽勝でした、助かった(´ー`;

という感じに完璧ではないですが、私はこの方法で最近は開発しています。ありがたい事にWindowsでDockerを使うためのwin-sshfsdokan(dokany)の開発が再開(?)されているため、Win10(64bit)環境でもきちんと動いてくれています。Dockerを使う人だけじゃなく、VirtualBoxやVMware等を使っていて、共有フォルダの挙動の重さに困っている人も試してみると良いかもしれません。

GRAPH APIのユーザIDからFacebookユーザへのリンク

2017年03月21日 | タグ: 開発

最近プログラミングに関する投稿をしてなかったので、軽めの内容ですが自分のための備忘録として。

Railsでアプリを作ってて、ログインをOmniauthを使ってFacebookと連携させるようにしていたのですが、この時受け取るユーザIDからFacebook上のユーザのページって見れないのかなって調べてみました。結論としては可能ですが、GRAPH API v2以降仕様が変わったみたいですね。

基本的にhttps://www.facebook.com/4(これはマーク・ザッカーバーグさん)のように、globalなIDが各自に振られているのですが、このユーザIDはAPIからは取得できません。以前はこの値をAPIで使用していたようですが、v2からは各アプリ毎に振られている模様です。

それじゃどうすれば良いのかと言うと、https://www.facebook.com/app_scoped_user_id/ユーザID/ の「ユーザID」の部分を置換することでユーザのページへのリンクとなります。

数ヶ月前にも一度調べたんですけど使っていなかったら忘れていて、また調べるのに時間かかったため書きました…最近こういうこと多いな…。しかしこれ、キーワードとしては何が良いのでしょうか? 国内の記事もあまり引っかからなくて(無いわけではない)。

Railsでのboolean型の命名

2016年11月19日 | タグ: Rails , 開発 , Web

かれこれ4年近くRubyとRailsを触っているのですが、それでもいまだに初歩的なことで「これ、どうしよう?」と悩んだり、「以前はこうしたけど、今回はどうしよう?」という問題にぶつかる日々です。

先日再びぶつかったのがタイトルのとおり、boolean型の値を保持するカラムの命名です。この手の問題は命名規約と既存のテーブルの板挟みに合うことがよくありますが、今回は新プロジェクトだったことと、Railsでのboolean型に関しては命名規約が見当たらなかったので余計に悩みました。

候補として挙がるのは2案ですね。例として削除フラグ(論理削除は筋悪という議論は置いておきます)を作ろうとした場合

1. deleted
2. is_deleted

この2つの間で悩みます。PHPをやってた頃はdelete_flagみたいな名前をつけているのを見かけましたが、Ruby界隈ではあまり見ない気がします。それと海外の文献を見ててもあまり見かけない気がしますが、私の観測範囲はそんなに広くないので偏見かもしれません。

話を戻して、1番か2番かで悩んでいるわけですが、今回参考にしたのはStack Overflowの回答でした。公式ドキュメントとかじゃないのかってツッコミは勘弁して下さい、見つけられなかったのです…。
convention - rails boolean fields: `is_foo` or just `foo`? - Stack Overflow
http://stackoverflow.com/questions/3112078/rails-boolean-fields-is-foo-or-just-foo

Railsでeven?, nil?, empty?, blank?といった使われ方をしているのに対してisで始まるのはis_a?ぐらいしか思い浮かばない、だから`is_`を取り除いた方が良いのではないだろうかというコメントが支持されていますね。Rubyでは変数の後ろに`?`を付けるとtrue falseの判定が行われるので、それもこのシンプルさの手助けをしています。

というわけで私はひとまず1番のdeletedを採用しました。とはいえ正解・不正解を見つけたわけではないのであくまで主観です。それに変数名によっては変更せざるを得ないので(例:public等の予約語)、高度の柔軟性を維持しつつ臨機応変に対処する必要がありそうです。

日報システムを作ってみました

2016年05月11日 | タグ: Rails , 開発

転職前の有給消化中もGW中も更新をサボってたりしたのですが、ようやく書く気になったので1つ報告でも。

昨年の夏頃から実装しては数週間放置し実装しては数週間放置しを繰り返していた個人で開発してたものを、先日GitHubに公開しました。ベンチャーや中小企業で使うのを想定した日報システムです。

日報システム

以前勤めてた会社で参考とした日報システムがあったものの、ちょっと実装がイケてない感じだったので「よし、個人開発で作ろう!」と思ったのがきっかけなのですが、公開にこぎつけた時点で退職しているとは想定していませんでした(ノ∀`;)

そんなわけで「誰が使うんだろうこれ」状態なのですが、もし興味があったら拾ってみてください。Railsが使える方なら簡単に手元で動かすことが出来ると思います。本格的に運用していこうと思うとちょっとRailsとサーバの知識が必要になるかも。

なおテストも書いてなければ人力テストも不十分ですので、バグが含まれている可能性が多分にあります。石を投げずにissue投げてくださいm(_ _;)m

何かレスポンスがあれば今後も継続して開発していくかもしれませんが、直近は別にやりたいことがあるので、しばらく放置になるかもです。というかこのblogも直したい、Bootstrapの理解が不十分だったのもあって色々酷いんですよね…。

sectionタグとh1タグで悩んだ末の結論

2016年01月02日 | タグ: 開発

正月の帰省で実家で暇だから自主的にちまちま進めてる開発をやってたのですが、sectionタグ内でのh1タグの扱いについて1時間程悩んだ結果、自分の答えに辿り着いたので忘れないようにまとめときます。そもそも数ヶ月前に調べたはずなのに頭から抜けてたんで(苦笑)

まずw3.orgのサンプルを見てみると、section毎にh1タグを使うのが推奨ではあるようです。こちらにサンプルがあります

それじゃh1タグ以外使っちゃいけないのか?というと、そうではないようで、sectionのネスト毎にHTML4.01の頃と同じようにhタグの番号を増やしていっても問題ないようです。というか、上記のサンプルをw3c validatorに通すとwarningが出るんですよ。こちらのページがそのwarningのリンク先である解説です。

要は「まだこのsectionタグを使った構造に対応してないブラウザなりscreen reader(目が不自由な方のためのソフトが主でしょうか)が対応してないかもしれないから、h1タグ以外を使った方がいいかもよ?」ってことですね。

このwarningに対してメーリングリストで疑問が出てたっぽいですね、ぐぐったら引っかかりました、こちらです。日付見て愕然、もう1年半ぐらい前から出てた問題じゃないですか、俺遅すぎる('A`)

上記メーリングリストの答えも踏まえた個人的結論として、不特定多数の大勢を対象としたサービスの場合はh1タグ以外も使った方が良さそうですね。一方自分が知ってる範囲内だけが対象で、使っても問題ないと思うようならh1タグだけでも大丈夫じゃないでしょうか。

とはいえh1タグ以外を使った場合でも、本来はh1タグを使うことが推奨されているわけで、そのうちh1タグだけに切り替えた方がすっきりすると思います。どのタイミングで全てのブラウザが対応したか調べるのが面倒しっかりとした判断つかないですが、w3c validatorのwarningから消えたらもうh1タグに切り替えれば良いんじゃないかなと思います。

個人的な結論はこんなところでした。まだ調べ足りない点もあるかもしれないので、指摘・意見等ありましたらTwitterからよろしくお願いします。

jQueryでformの挙動をあれこれ操作

2015年11月07日 | タグ: 開発 , Web

引越し関連で色々動いてたら更新の間が空いてしまったけど、いつもの事なので気にせず本題へ。

まず普通にformがあって、その情報で登録なり更新なりしたい状況にあるとします。ただし、エラーがあった場合はページの更新をせずに、エラーの理由を画面に表示させたいという要望があります。エラーが無ければ普通に遷移して問題ありません。

ここで実装したいこととしては

  1. 問題が無いかどうかvalidationを走らせる
  2. 問題があればエラーの表示、問題が無ければ更新

という流れの処理です。

まず1番ですが、これは普通にAjaxで送れば実現可能です。dataにどうやってformの値を突っ込めば良いんだろうって悩みましたが、検索してみたところ以下のような感じで実装可能でした。


$(function() {
  $('form').submit(function(event) {
    event.preventDefault();
    $.ajax({
      type: 'POST',
      url: 'hogehoge/validate',
      data: $(event.target).serialize()
    });
  });
})

適当に思い出しながら書いてるんで間違ってたらごめんなさい。$(event.target).serialize()でいい感じにデータまとめて渡せるっての初めて知りました、各所で使えそうですね。上記の返り値でerrorが返ってきたら適当にエラーを表示させて、successが来たら改めて登録を叩けば良いわけです。

が、今度はどうやって再びformのデータを送ればいいのかちょっと悩みました。またAjaxでデータを送る手もありますが、手動でリロードするのはなんか格好悪いなと。それなら普通にformをsubmitさせることは出来ないのかな、と。

一度preventDefaultしちゃったらこいつを復活させることは出来ないみたいでしたが、ちょっと探してみたら違う方法がありました。


$(function() {
  $('form').submit(function(event) {
    var formElement = $(this);
    // 中略
    formElement.submit();
  });
})

どうもformを取っておいて、submitを叩けば良いみたいです。これで普通にformのsubmitを実行したのと同じ結果を得ることが出来ました。めでたしめでたし。

…で、これ書いてて気付いてしまったのですが、そもそもの問題を解決しようと思ったら、別に1でvalidateだけじゃなくて実際更新させちゃえば、戻り値によってページのリロードするだけで済んじゃいますね。俺のバカ!y=ー( ゚д゚)・∵. ターン