rubyのメソッド引数が値渡しという話
Rubyを書き始めてまだ2〜3週間ですが、メソッドで思わぬ挙動があったので記録しておきます。
挙動が想定外だった
def test_add(arr) arr += [1] puts 'B=' + arr.to_s end def test_push(arr) arr.push(1) puts 'D=' + arr.to_s end arr = [0, 2] puts 'A=' + arr.to_s test_add(arr) puts 'C=' + arr.to_s test_push(arr) puts 'E=' + arr.to_s # => A=[0, 2] # => B=[0, 2, 1] # => C=[0, 2] # => D=[0, 2, 1] # => E=[0, 2, 1] ※想定外
おや?っと思ったのはEなのですが、メソッド外でarrにtest_push()処理値が反映されていました。 Rubyのメソッドは「すべて値渡し」というふうに記憶していたからです。
オブジェクトIDによる確認
Rubyはすべての値がオブジェクトなので、オブジェクトIDを確認することにしました。
def test_add(arr) arr += [1] puts 'B=' + arr.object_id.to_s end def test_push(arr) arr.push(1) puts 'D=' + arr.object_id.to_s end arr = [0, 2] puts 'A=' + arr.object_id.to_s test_add(arr) puts 'C=' + arr.object_id.to_s test_push(arr) puts 'E=' + arr.object_id.to_s # => A=69943959716760 # => B=69943959716500 ※これだけ異なる # => C=69943959716760 # => D=69943959716760 # => E=69943959716760
値渡しと言いながら、メソッド内外で利用されているオブジェクトIDが同じでした。 一点興味深かったのがarr += [1]をおこなったタイミングで新規オブジェクトが作成されている点です。
Rubyのメソッド引数はオブジェクトIDを値渡ししている
見出しの通り解釈することにしました。 そもそも参照渡しという解釈はメモリ上のポインタの話をした際に出てくるものなので、そこと混同すると参照渡しじゃないのか、という話になってくるのかと思いました。
オブジェクトをコピーして操作する
こう書けば想定通りでした。
def test_add(arr) arr += [1] puts 'B=' + arr.to_s end def test_push(arr) arr = arr.dup.push(1) puts 'D=' + arr.to_s end arr = [0, 2] puts 'A=' + arr.to_s test_add(arr) puts 'C=' + arr.to_s test_push(arr) puts 'E=' + arr.to_s # => A=[0, 2] # => B=[0, 2, 1] # => C=[0, 2] # => D=[0, 2, 1] # => E=[0, 2] ※想定どおり
フロントエンド環境構築(node/nvm/npm/gulp)
以前のプロジェクトでgulpを利用していたのに、フロントエンド担当ではなかったため環境構築に携われませんでした。 正直よくわからないで使っていたので、自分で構築して何をやっていたのか考えてみます。 今回は「ドットインストール」を教材に習ったもののメモになります。
dotinstall.com ↑なので、普通にこっちをやったほうがいい。
やりたいこと
環境(ちょっとアレンジしています)
- ubuntu(v14.04.4)
- node(v5.12.0)
- nvm(v0.31.2)※nodeのバージョン管理
- npm(v3.8.6)※nodeのパッケージ管理(gulpもパッケージのひとつ)
nodeバージョンについて
- 現時点で最新はv6.2.2だったがパッケージ対応が追いついていないものもあり、v5系で最新のバージョンを選択しました。
- ちなみに、LTS(Long-Term Support)とstableについてもぶつかったのですが、こちらに説明がありました。
インストール
- nvmを利用してnode/npmをインストール
$ git clone git://github.com/creationix/nvm.git ~/.nvm $ echo 'if [[ -s ~/.nvm/nvm.sh ]] ; then source ~/.nvm/nvm.sh ; fi' >> ~/.bashrc $ source ~/.bashrc $ nvm --version 0.31.2 $ nvm ls-remote : // 利用可能なバージョンが羅列される $ nvm install v5.12.0 $ nvm use v5.12.0 Now using node v5.12.0 (npm v3.8.6) $ nvm alias default v5.12.0 default -> v5.12.0 $ node -v v5.12.0 $ npm -v 3.8.6
プロジェクト作成
$ mkdir project project $ cd project project $ npm init : // 以下、エンターでOK(package.jsonが作成される) project $ npm install --save-dev gulp project $ touch gulpfile.js // あとでgulp実行内容を書く
- こんなファイル構成になりました。
project/ |-- node_modules/ | | : | |-- gulp/ | |-- gulpfile.js |-- package.json
タスクランナー(gulp)の実装
- gulpfile.js
// src -> dist var gulp = require('gulp'); var pkg = require('./package.json'); var imagemin = require('gulp-imagemin'); var coffee = require('gulp-coffee'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); var plumber = require('gulp-plumber'); var header = require('gulp-header'); var webserver = require('gulp-webserver'); // htmlファイルコピー gulp.task('html', function() { gulp.src('./src/index.html') .pipe(gulp.dest('./dist')); // htmlコピー }); // 画像ファイルコピー gulp.task('img', function() { gulp.src('./src/img/*.jpg') .pipe(imagemin()) // 画像圧縮 .pipe(gulp.dest('./dist/img')); // 画像コピー }); // JS作成 gulp.task('js', function() { gulp.src('./src/coffee/*.coffee') .pipe(plumber()) .pipe(coffee()) // JS変換 .pipe(concat('all.min.js')) // JS結合 .pipe(uglify()) // JS圧縮 .pipe(header('/* copyright <%= pkg.name %> */', {pkg: pkg})) // ヘッダー .pipe(gulp.dest('./dist/js')); }); // watch gulp.task('watch', function() { gulp.watch('./src/coffee/*.coffee', ['js']) gulp.watch('./src/*.html', ['html']) }); // webserver reload gulp.task('webserver', function() { gulp.src('./dist') .pipe( webserver({ host: '192.168.33.10', livereload: true }) ); }); gulp.task('default', ['html', 'img', 'js', 'watch', 'webserver']);
タスクランナーの実行
$ gulp
- 上記gulpfile.jsで実行される内容
画像ファイル名の難読化や、sassコンパイルなども同じ要領で追加していけると思います。 ざっくり何をやっているのか、どのようにやっているのかがわかりました。
PostgreSQLのインストール
UbuntuにPostgreSQLをインストールしてみました。 使い方についてもあまり知らなかったので、メモがてらCUI操作まで描いておきます。
パッケージのインストール
- こちらで本体、クライアントなど一通りの関連パッケージがインストールされます。
$ sudo apt-get update $ sudo apt-get install postgresql $ sudo aptitude install libpq-dev
- libpq-devはGemにて導入する際に必要とされたので、一応入れておくことにしました。
起動・終了コマンド
- MySQLやNginxとだいたい同じ
$ sudo service postgresql start $ sudo service postgresql stop $ sudo service postgresql restart
コンソール
- postgreというユーザーが作成されるので、最初はこちらでアクセス
$ sudo su - postgres // スイッチユーザー $ psql // PostgreSQL起動 postgres=#
- ついでにvagrantに権限付与(suしなくてすむようになる)
- ロール作成と、ユーザー名と同一のDatabase作成をおこなう。
postgres=# create role vagrant with createdb login; CREATE ROLE postgres=# \du List of roles Role name | Attributes | Member of -----------+------------------------------------------------+----------- postgres | Superuser, Create role, Create DB, Replication | {} vagrant | Create DB | {} postgres=# create database vagrant; CREATE DATABASE postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres vagrant | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | (4 rows) postgres=# \q ↑終了コマンド
- ちなみに、権限削除は「drop role vagrant;」となる。
GUIツールの利用(Mac)
こちらのツールを利用してみました。
設定はこんな感じ、vagrantユーザーでvagrantにSSHしつつ、ローカル(Vagrant内)のPostgreSQLにつなぐ感じです。 vagrantユーザーログイン時のデフォルトパスワードは「vagrant」です。
Vagrant上でNginx+Unicornサーバー設定
rails serverコマンドでアプリケーションサーバーを立ち上げるのも手間になってきたので、Unicornを入れてみました。 こちらは前回記事の続きの作業になります。
Unicornをインストール
- 以下、Vagrant内での作業になります。
- Gemインストールをおこなう
gem install unicorn
- bundle installをおこなう
$ cd /vagrant/myapp # プロジェクトディレクトリ $ vi Gemfile gem 'unicorn' # 書き足す $ bundle install
- unicorn.rbコンフィグの作成
$ vi /vagrant/myapp/config/unicorn.rb # 以下のような内容で新規作成する rails_root = File.expand_path('../../', __FILE__) rails_env = ENV['RAILS_ENV'] || "development" worker_processes 2 working_directory rails_root listen "/tmp/#{rails_env}_unicorn.sock" pid "/tmp/#{rails_env}_unicorn.pid" stderr_path "#{rails_root}/log/#{rails_env}_unicorn_error.log" stdout_path "#{rails_root}/log/#{rails_env}_unicorn.log"
- Nginx側設定
- conf作成
$ vi /etc/nginx/site_avabable/virtualhost-myapp.conf # nginx.confでincludeされる upstream unicorn { server unix:/tmp/development_unicorn.sock; } server { listen 80; server_name {指定ドメイン}; root {RAILS_ROOT}/public; access_log {LOG_PATH}/access.log; error_log {LOG_PATH}/error.log; client_max_body_size 100m; error_page 500 502 503 504 /500.html; try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn; } } $ ln -s /etc/nginx/site_avabable/virtualhost-myapp.conf /etc/nginx/site_enable/virtualhost-myapp.conf $ sudo service nginx restart
- Uniornを起動
$ bundle exec unicorn -D -c config/unicorn.rb -E development
$ sudo vi /etc/hosts # VagrantIPアドレスと指定ドメインをスペースで区切り記載 # グローバルに存在するドメインを記載すると、アクセスがVagrantに向いてしまうので注意! 192.168.33.101 {指定ドメイン}
コンフィグ等はこちらの記事にあったものを少し書き換えました。 - Rails4.2 を Nginx + Unicorn で動作させる - Shred IT!!!! - rails + nginx + unicorn連携 - Qiita
動作確認方法
$ ps aux|grep unicorn
developmentなんで開発系までですが、ざっくり動作しました。
Vagrant + Nginx + Ruby on Railsを動かしてみる
かなり遅まきながら、Rubyに触れる機会がありVagrantでのセットアップまでを試してみました。 RubyをVagrantにインストールし、Railsの新規プロジェクトを起動・ブラウザ確認するまでの工程をざっくり記載しました。
コマンドで迷ったところをメインにまとめてあるので、パッケージ不足のエラーなどは出力から判断し都度いれることで解消できると思います。
Vagrant構築
大まかな流れは以前やったので割愛します。
Rails Server起動時にport:3000を利用するので、Vagrantfileの設定を事前におこないます。 port:8080 --> 80 に加えてport:3000 --> 3000を追記します。 (わたしの手元環境ではphp/ruby/golangが混在しています…)
- ローカルPCのVagrantfile
config.vm.network "forwarded_port", guest: 80, host: 8080, id: "http" config.vm.network "forwarded_port", guest: 3000, host: 3000, id: "http"
Rubyをインストール
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build $ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
- パスを通す
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc $ source ~/.bashrc
- rubyバージョンを切り替える
$ rbenv install 2.3.0 $ rbenv global 2.3.0 $ rbenv rehash $ ruby -v ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
プロジェクト構築
- 引き続きVagrant内での作業になります。
- まずはgemをインストールします。
- Bundlerもここで入れてしまいました。
$ sudo aptitude install rubygems $ gem install rubygems-update // 自分を更新 $ gem -v 2.5.1 $ gem install bundler
- gemコマンドでrailsをインストール、プロジェクト作成
$ gem install rails
$ rails new myapp
- 初回はbundle installでコケますので、以下のエラーに対処してリトライする
- sqlite3をインストールする
$ sudo apt-get install sqlite3 libsqlite3-dev
- myapp/Gemfileでコメントされている'therubyracer'のコメント解除
- sqlite3をインストールする
$ cd myapp $ bundle install // リトライする
bundleのインストールパスについて
後々知ったのですが、bundle管理のパスは設定でき、プロジェクト下のvendor/bundleに保持するのが定石のようです。
$ bundle install --path vendor/bundle
こちらを実行することで、プロジェクト下に.bundle/configファイルとvendor/bundleディレクトリが作成されます。 プロジェクト単位でパッケージ管理ができ、本来用途に近しい実装ができます。
rails serviceを起動
こちら最後につまずきました。 localhostがruby専用だったら問題ないかと思いますが、今回は既存を残しつつport:3000を提供しているので、-bオプションで以下のIPを指定します。
vagrant: ~/myapp $ bundle exec rails server -b 0.0.0.0
こちらのブログで説明されていました。
Vagrant で Ruby on Rails 4 の環境構築 - Qiita
補足・RubyMineにてVagrantプロジェクトを設定
JetBrainのIDEを以前から利用していたのでRubyMineも使ってみたのですが、非常に便利に使えそうです。
ここまでおこなうと、基底も含めてRailsのコードをメソッドジャンプできるようになります。 最初にフレームワークを把握するのに便利そうなので、ぜひとも最初に設定してみましょう。
Unity Cloudで自動ビルドからSlack通知までを試してみました
Unityビルドの悩み
これまで実機での確認はPCにAndroid端末を接続して行っていました。 ただ、こちらの方法だと以下の懸念がつきまといます。
- ビルドが環境に依存する。(ProjectやSceneを保存し忘れる、Unityバージョンを揃えそこねるなど)
- 複数のプラットフォームでのビルドが手間。
- ビルド中、何も出来ない。
- テストビルドを他人に共有しづらい。
業務での開発であればビルドサーバーを用意することで連携をとっていると思いますが、個人開発だとそこまではなかなかできませんでした。 ところが最近、UnityのCloud Buildを利用することでこれらを一気に解決することができました。
https://unity3d.com/jp/services/cloud-build
基本的には無料で使える!
Asset Storeなどに登録していれば、同様のアカウントで利用が開始できます。 Unityでプロジェクトを作成し、Accountとのひも付けを行う方法がもっとも手っ取り早いです。
- 右上ボタンからアカウントを設定できます。
- アカウントを設定すると、Serviceウィンドウ(⌘0キーで表示)にクラウドプロジェクトを作るボタンが出てきます。
- 既存プロジェクトと結びつける事もできます。
- 「Select organization」ではプロジェクトの所属する組織を選択します。
- こちらはアカウントに紐付く情報でチーム名など決めていただけば良いと思います。
事前にクラウド側で設定しておくことでプルダウン選択できます。→ https://id.unity.com/organizations
設定が完了すると、各ステータス表示画面になります。
- SETTINGタブで「UNITY PROJECT ID」が確認できます
この時点ではクラウド上にローカルプロジェクトと紐ついたシンボルができたに過ぎません。 Serviceウィンドウの右上に「Go to Dashboard」のリンクが出ていると思うので、そちらをクリックしウェブ側の設定ページを開きましょう。
GitHubやBitBucketと連携する!
上の続きで、Cloud Build設定ページから新規作成したプロジェクトを選んでください。 わたしは仮に「Test」を作成しました。
「さあ、始めましょう」から順次、コード管理のサーバーURLやコラボレータの設定ができます。 (GitHubやBitBucketが使えます) サーバーURLはgit@github.com:user_name/project.git のようなパスを与えてやることでチェックアウトが可能かを調べてくれます。 Privateなリポジトリの場合はUnityが発行した公開鍵をコード管理プロジェクト側のデプロイ鍵に設定する必要があるのでご注意ください。
プラットフォームなどの設定も完了するとファーストビルドが行われます。
フリープランのビルドはそこそこ時間がかかるのでしばらく放置しておきましょう。 グリーンのチェックが入ればビルドは成功です。 (失敗・成功かかわらずオーナーにはデフォルトで完了メールが飛んできます)
メールやSlackでビルド完了を通知、テストユーザーも複数登録できる!
メールはデフォルトでオーナーに送信、それ以外のアドレスも「コラボレータ」タブから追加できます。 Slackは「Notifications」タブにあるボタンから設定できます。
開発用にチャンネルを作り、コードのコミット、ビルド結果などを纏めておくと非常に便利です!
現在の難点は無料だとビルドの連投ができず、1時間に1回程度までの制限があります。 とはいえ、これだけの機能が無料で利用できることは非常に便利ですし、個人開発も捗りますw
今後も良い機能がどんどん無料提供されていくことを願いつつ、技術習得に日々邁進していきたいと思います。
さくらVPSの独自ドメインサーバーからgmailにメールを転送
さくらVPSで独自ドメインを取得していたのですが、メールアドレスとして利用していなかったのに気づき、せっかくなので設定してみました。 これまでメールサーバーを構築したことがなかったので、基本的なことから勉強しました。
今回の要件
- さくらVPS独自ドメインでメールを受け取る。(仮にadmin@example.com)
- サーバー環境はubuntu、独自ドメインの設定(Aレコード)は終わっている。
- サーバーに持たず、gmailに転送する。
- セキュリティやフィルタの実装を考えると楽そうだったから。
マイルストーン
作業
PostfixとDovecotをインストールする。
// インストール $ sudo aptitude -y install postfix sasl2-bin dovecot-core dovecot-pop3d dovecot-imapd // postfixのconfigをカスタマイズ $ sudo cp /usr/lib/postfix/main.cf /etc/postfix/main.cf $ sudo vi /etc/postfix/main.cf // リスタート $ sudo service postfix restart // dovecotのconfigをカスタマイズ $ sudo vi /etc/dovecot/dovecot.conf $ sudo vi /etc/dovecot/conf.d/10-auth.conf $ sudo vi /etc/dovecot/conf.d/10-mail.conf $ sudo vi /etc/dovecot/conf.d/10-master.conf $ sudo vi /etc/dovecot/conf.d/10-ssl.conf // リスタート $ sudo initctl start dovecot
いろいろ割愛しましたが、configの設定は以下を参考にさせていただきました。
- http://www.server-world.info/query?os=Ubuntu_14.04&p=mail&f=1
- http://www.server-world.info/query?os=Ubuntu_14.04&p=mail&f=2
MXレコードを追加
さくら会員メニュー「会員メニュー > ドメイン > ネームサーバメニュー」からMXレコードを追加する。 追加方法はさくらVPSにキャプチャー付きで掲載されていました。
転送設定
$ sudo vi /etc/aliases $ sudo cat /etc/aliases # See man 5 aliases for format admin: xxxxxxxx@gmail.com # 転送元メールアカウント: 転送先にしたいメールアドレス postmaster: root $ sudo newaliases
挙動確認
tail -f /var/log/mail.log
上記エイリアス設定で、admin@example.com宛メールがxxxxxxxx@gmail.comに転送されます。