Quantcast
Channel: Rubyの記事一覧|TechRacho by BPS株式会社
Viewing all 1093 articles
Browse latest View live

[翻訳] Rails Guideの翻訳を進めました

$
0
0

こんにちは、hachi8833です。これまでチマチマ翻訳してきたRails Guideへのリンクをご紹介します。ガイド全体から見ればまだ半分ぐらいですが、サイズの大きいファイルから先に翻訳を進めてきたので、残っているのは比較的小さなファイルです。

注意: これらのファイルは今のところ翻訳が完了しただけであり、レビューなどはまだ行われていません。各人の責任でご利用ください。

補足: Githubに置いたことでmarkdownは簡易整形されていますが、画像は表示されません。Railsガイド ガイドラインに記載されている方法で Railsガイドをビルドすれば画像+CSSのあるガイドが得られます。
ファイル間のリンクはビルドが前提なので、そのままでは無効です。
訳していて怪しいと思った箇所には●を付けてとっとと先に進んでいます。
原文に忠実な訳とは限りません。原文より情報を増やしたり言い方を変えてあるところが多々あります。
たまに原文のdiffの残りが巨大な文字で表示されていることがありますが気にしないでください。
今後置き場所を移動する可能性がありますのでご了承ください。

Rails Guide (最近翻訳した分)

Rails Guide (これまで翻訳した累積分)

入門編

モデル関連

コントローラ関連

応用編

更新情報

小物ファイル


schemaをmodelに書き出してくれるgem annotate

$
0
0

こんにちは、kikedaです。
今回は、gem annotateを紹介しようと思います。小ネタです。

rails appを開発していると頻繁に、rake routeでルーティングを確認したり、dbからtableのschemaを確認することは、多々あると思いますが、私は、こういった手間を省くのにannotateを利用しています。
ただ、サポートしているruby, railsのversionについて、READMEには記載されていないので、ruby, railsのversionを記載しておくと。

$ ruby -v
# => 2.1.0-p0

$ rails -v
# => 4.1.5

この環境で動作を確認しています。

gem annotate

annotateは、各schemaの情報をファイルの先頭もしくは末尾にコメントをつけてくれるgemです。
schema、routingなどを直接ファイルを開くことで確認することができるようになります。

annotateの導入

rails appを想定していますので、導入は簡単です。
Gemfileに記載して、bundle installコマンドを実行します。

$ vi Gemfile

#... Gemfile
  gem 'annotate'

$ bundle install

schema情報の追加

tableのschemaをコメントとして追加

$ cd rails_app/
$ bundle exec annotate

fixtures
fixture.rb

test
test.rb

spec
spec.rb

factory
factory.rb

routingにコメントを追加 

$ cd rails_app/
$ bundle exec annotate --routes

route.rb

設定でファイルの末尾に記載することも可能です。

設定ファイルの作成

$ bundle exec rails g annotate:install

rake db:migrate時にannotateを起動してコメントを追加

$ vi lib/tasks/auto_annotate_models.rake

...省略
'skip_on_db_migrate'   => "true",
...省略

コメントをファイルの末尾に記載

ファイルの先頭に別のコメントが含まれている場合には、annotateのコメントを末尾に追加することができます。

$ vi lib/tasks/auto_annotate_models.rake

...省略
      'position_in_routes'   => "before",
      'position_in_class'    => "before",
      'position_in_test'     => "before",
      'position_in_fixture'  => "before",
      'position_in_factory'  => "before",
...省略

# beforeをafterに返ることでファイルの末尾に記載できます。
# annotateのコメントを末尾する場合は、下記のように直します。

      'position_in_routes'   => "after",

model_dirの値を変更することで,railsアプリ以外で利用することでもできます。

      'model_dir'            => "app/models",

以上です。ブラウザやrake routeコマンドを打って、出力されるのを数秒待つことなく、みることができるのは
小さなストレスを感じずに作業できるのでいいかと思います。

静的解析ツールgem RuboCop

$
0
0

こんにちは、kikedaです。

社内で、ソースコードレビューが活発になってきており、その私感を社内のミニプレゼンで発表しました。
ミニプレゼンの中で、ソースコードのコーディングルールを守って記述していたり、事前にチェックしておくと
レビューする側の人の負担が、減りますよね。という話をしました。

# 発表資料については、社内のコードやコメントを含めていたので、techrachoに記事は載せないつもりです。

コーディングルールについては、細かく指摘することは、コードを書く際のルールや決まり事を知ることができますし、一般的に読みづらくないコードを書く癖を付ける機会にはなります。
とはいえ、インデント、モジュール、クラス、メソッド、変数、などの命名規則のチェックや、誤字脱字レベルの誤りのチェックなどを、目grepで探すことは、レビュアーに負担を与えることになってしまいます。
レビューを依頼する人にとっても、こういった指摘が、多くでるのは嬉しくないはずです。(特に私)

チェックを事前にしておくことで、レビュアーにビジネスロジックのチェックや設計に関する意見や確認に集中してもらうことができるようになると思いますし、上記の通りこういった指摘が、減ることになりますから不快にならずにすみます。

ただ、さすがにテキストエディタなどでコーディングルールを守りながら記述したり、目で確認したりするのでは、非常に労力が、かかってしまいます。

そこで、静的解析ツールというgem RuboCopを紹介します。
Ruby以外でも、静的解析ツールはありますが、今回とりあげるのはRuboCopのみです。

RuboCop

RuboCopは、Rubyのコーディングルールをチェックしてくれるgemです。アップデートも頻繁に行われているようです。
hashの記述方法や、各インデントの有無、コメントの記法など様々な内容をチェックしてくれます。
デフォルトのまま利用することができますし、設定ファイルにコーディングルールの各項目を有効にしたり、変更したりすることができます。 

今回は、Railsのプロジェクトで利用すること想定しています。
続いて、RuboCopの導入方法とRuboCopの設定ファイル書いていきます。

RuboCopの導入 

$ rails new rails_app
$ cd rails_app
$ vi Gemfile

# ...
gem 'rubocop', require: false
# ...

$ bundle install

$ rubocop -R  # .rubocop.ymlにRunRailsCopsオプションを有効にすることでRオプションが不要になります

この状態で, RuboCopを実行するとRailsが自動生成したコードがコーディングルールが守られていないと言われてしまいます。
rubocopの実行結果

設定ファイル(.rubocop.yml)の作成

採用するコーディングルールは、下記を参考にすることにします。
ruby_on_rails#Follow the Coding Converntions

  1. 行の始めのインデントはスペース2文字
  2. 空行にはスペースを入れない
  3. hashの記述は、Ruby 1.9から採用されている記述を利用する{ a: :b }
  4. private/protectedの後はインデントを入れる
  5. &&/||ではなく、and/or
  6. 等号の前後にはスペースを入れる(a = b)
  7. メソッド引数を囲む括弧にはスペースを付けない
  8. { do_stuff }の前後にスペースを含める

Railsのrootディレクトリに作成するか、homeディレクトリに.rubocop.ymlファイルを作成します

  $ vi .rubocop.yml

READMEにも記載されていますが、 
RuboCopが採用しているデフォルトのコーディングルールは、Ruby Style Guideです。
そのため、デフォルトで、適用されるルールについては、.rubocop.ymlには記述せずにいきます。

パラメータについては、config/default.yml, config/disabled.yml, config/enabled.ymlで確認してください。
# Defaultsを参考
ソースを見ると、パラメータによっては、ruby-style-guideのリンクが張られていたりするので、どのコーディング規約に対応するのかがわかるようになっています。

AllCops:
  RunRailsCops: true 

Encoding:
  EnforcedStyle: when_needed

AccessModifierIndentation:
  EnforcedStyle: outdent

# 上記のルールにはないんですが、class Hogeの上にコメントを記述するのbest practiceとしてされていますが、
# ApplicationControllerとか記述したくなかったので、適用しないようにしました。
Documetation:
  Enabled: false

.rubocop.ymlの作成が完了したので、rubocopコマンドを実行します。

  $ rubocop

Railsから自動生成されるコードを一旦チェックから外す

RuboCopを調べているとこういった記事を読みました。.rubocop.ymlの設定例の記事も参考になりますが、コメントがついていて、それが良い情報だなと思いましたので、こちらもご紹介します。英語ができないので、非常に参考になりました。

rails new app_projectコマンドで、新規にプロジェクトを作成したときや、プロジェクトの途中からRuboCopを導入して、
ファイルを指定せずに、プロジェクト全体に対してrubocopを実行すると、自動生成されたコードや、既存のコードに対してもコーディングルールが守られているかをチェックします。ただ、自動生成のコードや既存のコードの、コーディングルールについては、
すぐに確認したり、修正したりすることは必要がない場合もあります。

その際に、rubocopコマンドに –auto-gen-configオプションを加えることで、.rubocop_todo.ymlが生成され、
その時点で、コーディングルールが守られていなかった項目については、.rubocop_todo.ymlに入力されて
Enabled: falseで該当する項目は、無効化されるように記述されます。
これをrubocop.ymlでinherit_from: .rubocop_todo.ymlとして呼び出すと、項目が無視されるようになります。
ただ、Enabled: falseにして、項目を無効化していますから、既存コードを修正しなければ、新規に追加したコードについてもコーディングルールをチェックすることができなくなります。

$ rubocop --auto-gen-config
$ vi .rubocop.yml

# .rubocop.yml
inherit_from: .rubocop_todo.yml

これで、.rubocop_todo.ymlに記載されている内容については、回避します。
時間があるときに、随時をtodoを消化して、プロジェクトのソースをコーディングルールに沿う形に進めていきましょう。
とはいえ、新規に追加していくコードについても、todoに記載されているコーディングルールを無視してしまうので、どこかで一気に直すか。
rubocopで、チェックするファイルを指定できるので、そちらでコントロールするかにしたほうが良さそうです。この辺りは調べていないのでちょっとよく知りません。

  $ rubocop

これで実行してみるとこんな感じになります。

todoファイル追加後

vimからRuboCopを実行

コマンドから実行するのではなく、各テキストエディタやIDEなどでプラグインが作られているようなのでプラグインを利用して、エディタからチェックするのもいいと思います。毎回ファイルを保存してから、コマンドからrubocopと打つのは大変ですよね。
vimなら、vim-rubocopというプラグインがあるのでそちらを利用することで、エディタ内でチェックできます。

詳しくは、vim-rubocop

ちなみに、作成したrubocop.ymlを読み込みことができます。

$ vi .vimrc
# .vimrc
let g:vimrubocop_config = '/path/to/rubocop.yml'

そのほかのエディタでも利用できるようになっているようです。

Guardを利用した自動チェック

利用するかは、好みですが、ファイルを保存した際にrubocopコマンドを実行したい場合は、guardを利用することで実現します。 

gem guard-rubocop
を参考にしてもらえればすぐ利用することができようになります。

  $ vi Gemfile

  group :development
    gem 'guard-rubocop'
  end

  $ bundle install
  $ guard init rubocop # Guardfileを新規に作成させる場合

以上になります。

参考

Google Driveのファイル共有状況を一括出力するgoogle-drive-permission-searchを作った

$
0
0

morimorihogeです。最近は遠征回すくらいしかやってなくて、6-1, 6-2も未消化です。流石に飽きてきたのかも。

共同作業やファイル共有に便利なGoogle Drive、仕事で使われている方も多いのではないでしょうか?
Google Driveは簡単に共有できて便利なのですが、進行中にメンバが出入りを繰り返す様なプロジェクトの場合、権限管理を忘れがちです。特に、新規共有するのは良いのですが、メンバがいなくなるときに正しく権限を外す処理は面倒なものです。
前半は、そうした場合のオペレーション方法を解説します。

また、ある特定のメンバについて検索する以外に、情報の整理として現在の手持ちドキュメント全ての権限を閲覧したいこともあるかと思います。後半はGoogle Driveの全ドキュメントの共有先を一覧するgoogle-drive-permission-searchを作ったので、それについての解説です。

Google Driveの検索オプションを使う方法

ある特定のメンバに対して共有されているドキュメントを一括検索したいときは、Google Driveのto:検索オプションが便利です。

参考: ファイルを検索する – ドライブ ヘルプ

例えばGoogle Driveの検索窓に「to:hoge@example.com」と入れて検索してやれば、hoge@example.comアカウントに閲覧・編集許可しているドキュメントが一覧されます。
共有を外したいファイルの左側チェックボックスをチェックして共有メニューを開けば、そのまま一括で共有状態を変更することも可能です。

Screenshot 2014-10-02 13.20.56

一般的なオペレーションならこれで大体どうにかなると思います。

全権限を一覧するgoogle-drive-permission-search

プロジェクトメンバやドキュメントが増えてくると、どのドキュメントが誰に共有されているのかが分からなくなりがちです。色々とドキュメントが蓄積されてくると、どこかのタイミングで全ドキュメントがそれぞれ誰に対して共有されているのか一覧したいということが出てきます。
また、機密情報などの情報管理上、いつの時点で誰に共有されていたのかを記録したい、ということもあるでしょう。

これはGoogle Driveの標準機能ではできないので、今回プログラムを書いてみました。

Github: https://github.com/morimorihoge/google-drive-permission-search

このプログラムを実行することで、以下の様なExcelファイルが生成されます(セルに改行を入れたかったのでExcelにしました。TSVもサポートしてます)。

Screenshot 2014-10-02 13.36.48

データ形式は以下の通りです。

  • A列: ファイル名
  • B列: ファイルタイプ(ファイルやフォルダ)
  • C列: データ形式(spreadsheetやformなど)
  • D列: ドキュメントID(主にデバッグ・他のプログラムでの読み込み用)
  • E列: 所有者情報(「名前 <メールアドレス>」形式)
  • F列: 共有先情報(権限: 「名前 <メールアドレス>」形式、複数人に共有されていれば改行区切り)

後は、Excelでフィルタするなり何なりすることで、よしなに管理することができるかと思います。

使い方

GithubのREADMEに書いておきましたが、すこし手順が煩雑なので解説です。
手順は google-api-ruby-client-sampleのREADME に一通りまとまっているのですが、始めてだと使い方がよく分からないかもしれないので、備忘録がてら解説してみます。

Google API Consoleでの設定

Google API Consoleにログインし「API & Auth」メニューから「APIs」を選択し、「Drive API」を有効化します。

Screenshot 2014-10-02 13.52.33

次に、「API & Auth」メニューから「Credentials」を選択し、OAuthの「Create new Client ID」を開きます。「APPLICATION TYPE」は「Installed Application」、「INSTALLED APPLICATION TYPE」は「Other」を選択します。

Screenshot 2014-10-02 13.57.35

Screenshot 2014-10-02 13.56.42

これで「Client ID for native application」が生成されるので、接続情報のJSONファイルをダウンロードし「client_secrets.json」というファイル名で保存します。

Screenshot 2014-10-02 14.56.52

あとはこのclient_secrets.jsonをgithubからcloneしてきたディレクトリに配置すれば準備完了です。
client_secrets.jsonはAPI利用の認証情報が入っているので、他の人に渡さないように注意して下さい。

実行方法

Ruby 2.0.0以上+bundlerがインストールされていれば、以下の通りで動くと思います。

git clone https://github.com/morimorihoge/google-drive-permission-search.git
cd google-drive-permission-search
cp ~/client_secrets.json ./
bundle
bundle exec ./google-drive-permission-search.rb --type excel -v

ドキュメント数が多いと時間がかかる(400ドキュメントで数分程度)ので、-v/–verboseオプションで途中経過を表示すると良いかもしれません。
その他のオプションはREADMEを参照して下さい。–only-includesを使えば特定のユーザに共有されたドキュメントで絞り混むことも可能です。

まとめ

Google Driveは気軽&柔軟にファイル共有できる反面今一つ権限情報の見通しが悪いのが難点です。本記事ではGoogle Driveの検索機能を使う方法と、google-drive-permission-searchを使って全ファイルの権限リストを取得する方法を紹介しました。
大事なファイルがいつの間にか知らない相手に共有されていないかチェックするのにでも使って頂ければと思います。

個人的にGoogle Drive APIは一度は触ってみようと思っていたので良い機会でした。Rubyではgoogle-api-ruby-clientという公式Gemがあるので割と楽に開発できました。
またそのうち気が向いたらGoogle Driveをごりごり使うアプリでも書いてみようかと思います。

ではでは

Railsで大きなファイルを扱う際のポイント

$
0
0

Railsで大きなファイルを扱う際のポイントをまとめてみました。

前提

大きなファイルとは

だいたい100MB~10GBくらいのファイルをダウンロード・アップロードするのを想定することにします。
数MB程度だと、特別な工夫なしでもそれほど問題になりません。10GBを超えてくると、気をつけるべき点が変わってくるかと思います。

以下では主にサンプルとして、1GBのファイル(ISOファイルやZIPファイルなど)を想定します。

環境

以下のような環境を想定します。

  • Railsは4系
  • Nginx + Unicornのスタンダードな構成
  • サーバ1台のシンプルな構成(ロードバランサを使用した複数台構成については、末尾に少し記載しています)

ダウンロード

ファイルのダウンロード

まずは、Railsアプリから大きなファイルを配信するケースを考えましょう。
たとえば、ISOファイルをサーバ内に保存しておいて、認証されたユーザはそれをダウンロードできる、というケースです。

シンプルに実装すると、このような感じになると思います。

# app/controllers/files_controller.rb
class FilesController < ApplicationController
  def show
    send_file Rails.root.join("files/01.iso")
  end
end

しかし、巨大なファイルをRailsが配信するのは、よく考えるとかなり無駄です。
1GBのISOファイルを配信する場合、クライアントとの帯域が50Mbps確保できたとしても、単純計算で160秒間ワーカーが占有されることになります。これでは、Unicornのワーカーを50個用意してもすぐになくなってしまいます。

ファイルを送信するだけなら、Reverse Proxyとして使っているNginxやApacheに処理してもらった方が効率的ですよね。Nginxなら、同時接続数3000くらいあっても余裕でしょう。

方法1: publicに置く

アクセス制限が不要なら、publicなディレクトリにファイルを配置し、そのままNginxやApacheで配信してしまえば良いです。スタイルシートなどのassetsも、この方法で配信します。

方法2: X-Sendfile / X-Accel-Redirectを使う

認証が必要な場合、Rails側からX-Sendfileを指定すると良いでしょう。
方法は、production.rbで以下の行を記述するだけです。デフォルトではコメントアウトで記載されていると思います。

# config/environments/production.rb
# ...
    # Apacheを使う場合
    config.action_dispatch.x_sendfile_header = 'X-Sendfile'

    # Nginxを使う場合
    config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
# ...

これを記載すると、RailsはISOファイル本体を読み取ってResponse Bodyを送信する代わりに、HTTPヘッダに「X-Accel-Redirect: /path/to/files/01.iso」のようなヘッダを付与し、Response Bodyを空にしてレスポンスを終了します。そのヘッダを受け取ったNginxがpublicディレクトリの場合と同じようにファイルを送信するため、Railsのワーカーはすぐに解放されます。

これは内部的にはRack::SendfileというMiddlewareで実現されているので、Sinatraなどで活用することも可能です。

方法3: 別のサーバから配信する

静的ファイルなら、S3など別のサーバに置いておけば、帯域などの心配をせずにすんで楽です。
認証が必要な場合でも、S3のAPIで有効期限付きのURLを発行できるので、問題ないでしょう。
ダウンロード数が多い場合は、検討すべきです。

ストリーミングダウンロード

データがサーバ上の実ファイルではない場合、Railsで順次送信するしかありません。
データの生成に時間がかかる場合(巨大なPDFを作る、別サーバからダウンロードしたデータを順次流すなど)、すべてのデータが準備できる前に送信開始したいものです。

その場合は、response.streamを使用します。
http://api.rubyonrails.org/classes/ActionController/Streaming.html

# app/controllers/download_controller.rb
class DownloadController < ApplicationController
  include ActionController::Live

  def show
    3.times do 
      response.stream.write "Some Data"
      sleep 1
    end
  ensure
    response.stream.close
  end
end

いくつか注意点があります。

なるべくContent-Lengthを指定する

事前にContent-Lengthを指定しておけば、ブラウザ側で「何%ダウンロード中…」とプログレスが表示されます。
もちろん、ヘッダはボディ送信後には送信できないので、最初のデータを送信する前にContent-Lengthを指定する必要があります。

pumaなど対応サーバを使う

UnicornやPumaなどのサーバなら問題ありませんが、Webrickなどを使うとストリーミングが動作しません。
この場合、レスポンスがすべてバッファリングされるため、実質通常レスポンスと同じような挙動になります。

エラー処理を工夫する

データ送信中にエラーが発生しても、すでにレスポンスコードは返しているため、あとからInternal Server Errorに変更するわけにもいきません。
このあたりは設計でカバーする必要があります。

上段でのバッファリングを無効化する

上段のReverse Proxyで、結局全部バッファリングされてしまうようなケースもあります。Nginxなら、X-Accel-Bufferingなどを確認しましょう。

また特定バージョン(忘れました)で、Keep-Aliveとバッファリングの設定によって、Rails側からcloseしてもタイムアウトまでレスポンスを待ち続けてしまうことがありました。なにやら30秒~60秒くらい固まってしまうときは、この辺のバグも疑ってみましょう。

アップロード

次は、大きなファイルをアップロードするケースを考えてみます。
たとえば、ファイルアップローダを作る場合です。ファイルアップロードには、CarrierwaveのGemを使うことを想定します。

クライアントサイドの工夫

クライアント側は、通常のHTMLによる<input type="file">でも良いですが、これだとアップロード中に固まったように見えるため(最近のブラウザではステータスバーに進捗が出ることはありますが)、UXとしてはいまいちです。

jQuery File Uploadなどを使えば、視覚的なプログレスバーを表示できるのでおすすめです。なお、今回はクライアント側についての詳細は省きます。

何も工夫しない場合

単純に実装すると、このような流れになります。

upload1

青い部分がデータ転送やファイルコピー・移動で、上下の太さはかかる時間の大小を表すつもりで見てください。1GBのファイルをアップロードする場合では、以下のような点で時間がかかります。
ファイルアップロードに関係ない各種処理やオーバーヘッドは除外しています。

1. ブラウザからNginxへHTTP送信
通常、一番時間がかかる部分です。帯域に依存します。たとえば実効速度で50Mbpsの帯域なら、160秒程度かかります。
2. NginxからRailsにHTTP送信
Nginxがバッファリングしたデータを、Railsアプリに送信します。Reverse ProxyであるNginxとRailsアプリは、通常ローカルネットワークまたは同一マシンにあるため、帯域は十分でしょう。仮に800Mbpsとして、10秒程度かかります。
Railsアプリが受信したデータは、Rackのレイヤーで一時ファイルに保存され、Rack::Multipart::UploadedFileとしてControllerから参照できます。
3. Carrierwaveのcache dirにコピー
Carrierwaveは、Rack::Multipart::UploadedFileを一時ディレクトリにコピーします。これはローカルストレージ内でのコピーなので比較的高速です。仮に200MB/秒として、5秒程度かかります。
4. Carrierwaveの途中処理
version指定をした場合など、ここで加工処理(たとえばImageMagickで画像縮小)が実施されます。今回はシンプルなアップローダなので、何もしません。
5. Carrierwaveのstore dirにコピー
モデルをsaveするタイミングで、cache dirに保存されたファイルを、保存ディレクトリにコピーします。これはローカルストレージ内でのコピーなので比較的高速です。仮に200MB/秒として、5秒程度かかります。

これでようやく、クライアントに「アップロード完了」のレスポンスを送信できます。ブラウザから見た時間を合計すると、

  • (A) リクエスト送信開始~送信完了するまで: 160秒
  • (B) リクエスト送信完了~レスポンス受信開始まで:20秒

となります。

ここで、(A)はある程度仕方ないのですが、(B)に20秒かかっていることが問題です。これだけ時間がかかると、ファイルサイズ次第でクライアント側がタイムアウトしてしまう恐れがあります。

サーバ側での対策

そこで、大きなファイルを扱う場合には、以下のような対策を両方実施するのが有効です。

  • リバースプロキシ(Nginx)とRailsを同一マシンで動作させ、Nginx upload moduleを使う
  • Carrierwaveでmove_to_cache, move_to_storeをtrueにする

Nginx upload moduleを使う

「2. NginxからRailsにHTTP送信」で、NginxからRailsに巨大なファイルをHTTP経由でRackに渡している部分は、大きな無駄です。そこで、Nginxが直接一時を生成してしまうのがNginx upload moduleです。

http://wiki.nginx.org/HttpUploadModule

Nginxの設定方法は概ね以下のような感じです。

# Ubuntuでは以下のコマンドでupload moduleをインストールできる
apt-get install nginx-extras
# /etc/nginx/nginx.conf
# nginxの実行ユーザとRailsの実行ユーザを同一にする。
# これをしないと、CarrierWaveがchmodするときにエラーになる。
user my_app_user;
# /etc/nginx/sites-available/my_app.conf
upstream my_app {
  server 127.0.0.1:8080;
}

server {
  listen 80;
  root /home/my_app/rails/current/public;
  client_max_body_size 5g;

  location / {
    try_files $uri @application;
  }

  location ~ ^/upload$ {
    if ($request_method = POST) {
      upload_pass @rails;
      upload_store /tmp;
      upload_store_access user:rw group:rw all:rw;
      upload_set_form_field "$upload_field_name[filename]"   "$upload_file_name";
      upload_set_form_field "$upload_field_name[type]"       "$upload_content_type";
      upload_set_form_field "$upload_field_name[tempfile]"   "$upload_tmp_path";
      upload_aggregate_form_field "$upload_field_name[md5]"  "$upload_file_md5";
      upload_aggregate_form_field "$upload_field_name[size]" "$upload_file_size";
      upload_pass_form_field ".*";
    }
  }

  location @rails {
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_buffering off;
    proxy_pass http://my_app;
  }
}

このモジュールを利用すると、Nginxがファイルアップロードのリクエストを受け付けた際、それをProxy先に転送する代わりに指定ディレクトリに保存するようになります。
RackにはNginxが作成した一時ファイルのパスだけが渡されるので、「2. NginxからRailsにHTTP送信」で10秒かかっていた処理は一瞬で完了します。ただしそのままだとRack::Multipart::UploadedFileが生成されないため、Railsアプリ側で多少処理が必要です。

# app/controllers/upload_controller.rb
class UploadController
  # POST /upload
  def upload
    file = ensure_uploaded_file(params[:file])
    # ...
  end

  private
  # Nginx upload module経由で受信した"tempfile"パラメータを参照し、
  # 手動でActionDispatch::Http::UploadedFileを作成する。
  #
  # Nginx設定をしなくても低速ながら動作するように、ifチェックを入れておく
  def ensure_uploaded_file(file_or_hash)
    if file_or_hash.is_a?(Hash) && file_or_hash[:tempfile]
      # Nginx upload module経由の場合
      file_or_hash[:tempfile] = File.new(file_or_hash[:tempfile])
      ActionDispatch::Http::UploadedFile.new(file_or_hash)
    else
      # 通常の場合
      file_or_hash
    end
  end
end

Carrierwaveでmove_to_cache, move_to_storeをtrueにする

Carrierwaveでは、デフォルトでファイルを2回コピーします。これは、画像のサイズ変換などをしやすいほか、Permission問題が起きづらいメリットがあるのですが、大きなファイルにおいては非常に大きな時間の無駄です。

今回のようなシンプルなアップローダでは、コピーの必要はないので、mvしてしまいましょう。これは、オプションを指定するだけで簡単にできます。
もちろん、Nginx upload moduleで指定するupload_storeと、最終的な保存先であるstore_dirは、同じパーティションにする必要があります。

# app/uploaders/files_uploader.rb
class FileUploader < CarrierWave::Uploader::Base
  storage :file

  def move_to_cache
    true
  end

  def move_to_store
    true
  end
end

これにより、Nginxが作成した一時ファイルが、そのまま最終的なstore directoryに移動されることになります。移動は一瞬なので、「3. Carrierwaveのcache dirにコピー」「5. Carrierwaveのstore dirにコピー」がほぼゼロになることになります。

合計すると以下のようになります。

  • (A) リクエスト送信開始~送信完了するまで: 160秒
  • (B) リクエスト送信完了~レスポンス受信開始まで:ほぼ0秒

upload2

通常のアクションと同じ反応速度を実現できるようになりました。めでたしめでたし。

ところで

お気づきかと思いますが、これだけやってようやくPHPでmove_uploaded_file使うのと同じになっただけです。特別早くなったのではなく、普通になったのです。

多段Proxyの場合どうするのか

  • 負荷分散のため、Reverse ProxyとRailsアプリを別マシンにしたい
  • グローバルIPの関係で多段Reverse Proxyしたい

このような場合は、前段にNginxを使うのはあきらめましょう

現バージョンのNginxでは、ProxyにUploadする際にはリクエストをすべてBufferingする必要があります。
そのため、多段ではどうしても上記「2. NginxからRailsにHTTP送信」に相当する時間がかかってしまいます。

upload3

対策としては以下のようなものが考えられます。

  • もうすぐ実装されるらしいので、それを待つ
  • バッファリングせずにアップロードできるReverse Proxyを使う
    • Tengine (Nginxのfork) だと実現できるらしい
    • 多くのロードバランサーもおそらく大丈夫でしょう

まとめ

本記事の内容を活用すれば、RailsでもPHPを普通に使うのと同じ程度のことはできるようになると思います。小規模チーム用のアップローダを作る程度なら、この程度で十分でしょう。
小規模なら本当にRailsで実装する必要があるのかは疑問ですが、使い慣れたツールでのやり方を把握するのは無駄ではないでしょう。

アクセスの多い公開用サイトでは、先に帯域の問題と向き合わなければならず、アプリだけでなくインフラやサービスレイヤーでの工夫が必須になります。そのあたりは今回触れていませんが、おもしろいテーマなので機会があれば検証してみたいですね。

1年近く前に小規模なファイルアップローダを実装した際の記憶で書いているため、誤りがあればご指摘いただけば幸いです。

RubyWorld Conference 2014参加します&スポンサー登録しました

$
0
0

morimorihogeです

RubyKaigi 2014も終わり、次はRubyWorld Conference 2014(11/13(木)-14(金))のシーズンになりました。
今年は弊社もスポンサーとして登録させて頂きました。当日はTechRacho関連のチラシも配布予定です。

まだ参加募集中の様ですので、参加予定の方はぜひ現地でお会いしましょう!
RWC2014_SPONSORbanner_B

・・・と、宣伝だけというのも何ですので、去年撮った写真を今頃何枚か貼っておきます。

会場のくにびきメッセ
IMG_2019

メイン会場はこんな感じ。写真は最終日のRuby Prize発表時のものですね。
IMG_2033

松江のごはんはおいしかったです。今年も楽しみ。
IMG_2010

写真が見つからなかったので画像は無いですが、松江はビアへるんの倉本もあるので、地ビール好きな人は松江駅前のエスパークというお店に行けば生で飲めますよ!

なんだか観光案内みたいになってしまいましたが、終わったらレポート記事を書こうと思います。ではでは。

【速報】RubyWorld Conference 2014前夜レポート@松江

$
0
0

morimorihogeです。秋イベに向けてとりあえず鋼材はカンスト、一番少ないボーキでも16万までは貯めました。これで資源切れはないだろう(心が折れないかどうかは別

明日から始まるRubyWorld Conference 2014に向けて、一足早く松江にやってきました。
去年は弊社hachi8833を含むメンバでレンタカーを使っての強行軍でしたが、今回はおとなしく僕一人での参加です。
当日朝イチの便でわたわた来るのも大変だなと思いましたので、前日入りしてみました。以下は夜の宍道湖の写真です。

IMG_2902

個人的に目を付けていた居酒屋さんに突撃したところ、松江は先週辺りに蟹が解禁となり、冬の魚もぼちぼち出てきた所のようです。のどぐろがごろごろ並んでました。すばらしい。
また、松江のRuby浸透率は相当なものの様で、カウンターの隣でお会いした方は陶芸をやられていたそうなのですが、Rubyという単語が通用しました(宝石のRubyじゃなくてちゃんとプログラミング言語として)。松江すごい!

IMG_2903

島根名物の赤てんも頂きつつ、明日は朝からconferenceに参加したいと思います。

IMG_2906

今回、RubyWorld Conferenceに合わせてリクラッチョをリリースしました。本TechRachoは引き続きエンジニアが技術情報を発信する場として成長を続けつつ、リクラッチョでは転職・求職をされているエンジニアの為のサイトとして仕事先の紹介をしていければと思っています。
また具体的な展開は弊社大場などからもプレスリリースが出るかと思いますが、一足先にお知らせさせて頂きます。

それでは、明日からconferenceに参加される方はよろしくお願いいたします!もし当日僕に連絡したい(仕事相談、ただの雑談、飯一緒に食おうぜなど)という方がいらっしゃいましたらTwitterで@morimorihogeまでご連絡頂ければ対応させて頂きます。よろしくお願いいたします。

FactoryGirlでHasManyな関連モデルも同時に生成する

$
0
0

下のようなBookとPageというモデルがあったとして、Bookを作成する際にPageも一緒に作りたいという場合。

環境

class Book < ActiveRecord::Base
  has_many :pages
  accepts_nested_attributes_for :pages
  validates :pages, length: { minimum: 1 }
end
class Page < ActiveRecord::Base
  belongs_to :book
  validates :book, presence: true
end

FactoryGirlではこう書ける

FactoryGirl.define do
  factory :book do
    title  "タイトル"
    after(:build) do |book|
      book.pages << build(:page, book: book)
    end
  end
end

これでBookを作成した時に配下のPageもひとつつくられる

FactoryGirl.create(:page)

CapistranoでGitのサブディレクトリ以下をデプロイする

$
0
0

備忘録を兼ねてメモ。 Gitのサブディレクトリ以下とは、例えばこんな構成です。 通常であればRailsアプリがGitリポジトリ直下にありますが、 複数のRailsアプリがあるなどしてデプロイしたいアプリがGitリポジトリのサブディレクトリ以下にある場合です。

repogitory/
      ├── user   # エンドユーザー向けのRailsアプリケーション
      ├── admin  # 管理者向けRailsアプリケーション
      ├── core   # Modelなど各アプリから参照されるRailsエンジン

Gitリポジトリ直下にアプリがある場合は、言わずもがなCapistranoで簡単にデプロイできますよね。 けど、今回のようなケースですと一工夫してやる必要があります。 stackoverflowに解決案がありました。

Strategyの追加

require 'capistrano/recipes/deploy/strategy/remote_cache'

class Capistrano::Deploy::Strategy::RemoteCacheSubdir < Capistrano::Deploy::Strategy::RemoteCache
  private
  def repository_cache_subdir
    if configuration[:deploy_subdir]
      File.join repository_cache, configuration[:deploy_subdir]
    else
      repository_cache
    end
  end

  def copy_repository_cache
    if copy_exclude.empty?
      run "cp -RpL #{repository_cache_subdir} #{configuration[:release_path]} && #{mark}"
    else
      exclusions = copy_exclude.map { |e| "--exclude="#{e}"" }.join(' ')
      run "rsync -lrpt #{exclusions} #{repository_cache_subdir}/* #{configuration[:release_path]} && #{mark}"
    end
  end
end

deploy.rbの設定

require './lib/deploy/strategy/remote_cache_subdir'
set :strategy, Capistrano::Deploy::Strategy::RemoteCacheSubdir.new(self)
set :deploy_subdir, -> 'admin'

あけましておめでとうございます。今年もよろしくお願いいたします。

$
0
0

いつも弊社およびTechRachoを応援くださり誠にありがとうございます。おかげさまで2014年も乗り越えることができ、2015年早々ドタバタしております。新しい目標に向かって進むのと、新しい体制を構築するのを同時にやろうとすると、いつもより少し緊張しますね。計画性が足りないのか、案件ごとのビジネス感覚が弱いのか、日々の状況の変化に対応しきれていないのか、恐らく全部当てはまる気がしています。いずれにせよ弊社を頼ってくださる方々、一緒に頑張ってくださる方々、旧年はとてもとてもお世話になりました。いつもありがとうございます。今後ともどうぞよろしくお願いいたします。

新たに始める事業や取り組みを紹介します。

まずは採用支援を初めます

TechRachoの読者向けにRecRachoというリクルートサービスを開始します。RecRachoについての詳細はこちらにまとめました。
RecRachoバナー

漫画翻訳事業はさらに拡大させます

漫画翻訳サンプル

今年で累計2000件の翻訳を担当させていただきました。その99%が漫画の翻訳です。言語も英語や中国語だけでなく、スペイン語、フランス語、韓国語に伸ばしつつあります。弊社の漫画翻訳の事業ページはこちらです。ぜひご覧ください。

Ruby on Railsによるシステム開発もさらに拡大させていきます

railslp
2007年から続けているWEBシステム開発の受託開発事業部です。今では大変光栄なことに取引先も増え幅広い業態へのシステム導入を経験させていただきました。引き続きお役に立てるように人員の採用と育成、そして会社規模拡大に注力します。

[CSS][ルビ] CSS研究部Webを更新しました

$
0
0

CSS研究部Webを更新しました。9月に行った勉強会の書き起しです。
今回はPart分けはなく、1本のみです。

* CSS研究部 第三回部会 – New!

本日更新分は、ルビについて扱っています。ルビは日本語に欠かせない表現のひとつです。

group-xo-54682063

440px-Railgun-1.svg-f92d7ab0

今後の予定については、CSS研究部のWikiをご覧ください。

この部会はCSS仕様の先端に切り込もうとしている分、記事に不備が残っているかもしれません。お気付きの点がありましたら、記事の末尾にコメントをいただけると助かります(Disqusを使用しています)。

論理削除用paranoia gemがあるRailsプロジェクトで物理削除する方法

$
0
0

こんにちは、hachi8833です。

データベースで何かと問題になる論理削除ですが、他所から引き取ったRailsプロジェクトでparanoia gemが使われている場合に止むを得ず物理削除を行うための方法をメモします。記事末尾のコメントもご覧ください。

160915_1557_nhXqGK

paranoiaでの物理削除

ActiveRecordオブジェクトで#really_destroy!を呼べば物理削除になります。

>> client.really_destroy! # => client

それ以外のdestroy系操作は期待どおり論理削除(実際には削除せず、隠すだけ)になります。

注意: 以下にあるように、関連するすべてのdependent: :destroyレコードも物理削除されます。

WARNING: This will also really destroy all dependent: :destroy records, so please aim this method away from face when using.
rubysherpas/paranoia

160915_1638_Ae7tXA

確認したところ、paranoiaの#deleteで以下のメソッドがオーバーライドしているので、#deleteでは物理削除されなくなります。

  def delete
    raise ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
    if persisted?
      # if a transaction exists, add the record so that after_commit
      # callbacks can be run
      add_to_transaction
      update_columns(paranoia_destroy_attributes)
    elsif !frozen?
      assign_attributes(paranoia_destroy_attributes)
    end
    self
  end

以上です。

paranoia gemの利用法

基本的な利用法もメモします。paranoiaのリポジトリそのまんまですが。

モデル(ここではClient)でacts_as_paranoidを追加することで論理削除が有効になります。

class Client < ActiveRecord::Base
  acts_as_paranoid

  # ...
end

以後、このモデルのインスタンスでdeleted_atdestroyを呼んでもdeleted_atタイムスタンプが追加されるだけで実際には削除されなくなります。

>> client.deleted_at # => nil
>> client.destroy    # => client
>> client.deleted_at # => [タイムスタンプ]

よく使いそうなメソッドとスコープ

Client.allに論理削除済みのものも含める場合:

Client.with_deleted
Client.without_deleted  #=> 'without_default_scope'を指定しているなどの理由でdefault_scopeが使えない場合向け

論理削除済みのものだけ取り出す:

Client.only_deleted

論理削除済みかどうかのチェック方法(2種類):

client.paranoia_destroyed?

client.deleted?

論理削除を取り消す方法(2種類)

Client.restore(id)

client.restore

コメント

morimorihogeです。最近はコメントの人化してますね(汗

論理削除というとはてブ界隈で定期的にマサカリが飛び交う界隈ですが、大方の議論はDELETE_FLAG を付ける前に確認したいことで網羅されているので、投げる前にまずはこちらを参照しましょう。その上で議論する方がお互い有意義です。

#社内Slackでも定期的に話題になります

僕自身はRailsにおける論理削除はunique indexがどこかのカラムに付いてるとActiveRecordのuniqueness validationをくぐり抜けてSQLがエラーになったり、後から論理削除対応しようとするとdefault_scope周りで問題になったりで困ることが多いので、基本使わない派です。ブツリサクジョコワクナイヨ

ただ、どこかの誰かが作ったコードが保守・引き継ぎで回ってくることまでは避けられないので辛みですね。db/schema.rbをとりあえず見たときにステータスっぽいフラグが大量にあるテーブルを見ると心が荒みます(フラグなのにbool以外な値が入ってる奴とかは特に)。

ところでRailsではあまりRDBMSのVIEWを使わない文化な感じですが、複雑なscopeでフィルタリングされた条件を参照するときなんかはscopeよりもVIEWの方がシンプルじゃないかなあと思うことはあります。

たとえば、商品テーブル(products)があったときに「今販売可能な商品」という条件が「公開フラグがON」かつ「現在時刻が販売期間内含まれている」かつ「在庫がある」・・・(以下略)みたいなことは良くあると思うのですが、scopeで条件を作ってしまうとRailsコードからアクセスするのは便利なのですが、同等の条件を取り出すSQLが欲しい、となったときに色々不便です。

こんな時「v_current_available_products」の様なVIEWを定義しておけば、何も考えずにVIEWから取り出すことができるんですよね。VIEWはSELECTする限りにおいては通常のテーブルと同じように使えますし。
#scopeだと引数付きscopeなんかをメソッドチェーンで使えるメリットはあるっちゃありますが、同等のVIEWは作れるはず

と思ってここまで書いていたらVIEWを使われている事例がありました (DBのViewを作ったらRailsプログラムが綺麗になった話)。まあ、RailsでVIEWを扱う時はmigrationの絡みも出てきてまた違う辛みも出てくるので万人にオススメできるかというと辛いところもあるのですが、選択肢としてはアリだと思います。

ただ、MySQLにはマテリアライズドビューがないので、VIEWを多用するようなプロジェクトではPostgreSQLを使うか、更新頻度がそう頻繁でなくて良ければ擬似的にマテリアライズドビュー相当のテーブルを作るということになります。(参考:MYSQLで疑似的なマテリアライズド・ビュー作成)

いつの間にか話題がそれましたが、論理削除に限らずフラグやステータスについてはよくよく考えて行きたいものですね。「XXさんに聞かないとこのフラグの意味は分からない」とかにはなりたくないモノです(しみじみ)。

関連記事

sprintfよりRubyらしく書けるフォーマット文字列メソッド「Strings#%」

$
0
0

こんにちは、hachi8833です。

書式付き文字列メソッド「Strings#%」

160915_1236_ZwW4zt

Strings#%は、Kernel.#sprintfと同様の書式付き文字列メソッドです。

putspなどの出力以外でも使えますし、Kernel.#sprintfよりも生々しくないので、よりRubyらしく文字列フォーマットできるStrings#%を活用するとよいでしょう。あまり凝った書式にすると可読性が落ちるかも。

160915_1716_glxg8m

オプション

Strings#%の書式オプションは、ドキュメントにもあるようにC言語のsprintf(3)とだいたい同じです。というより多くはsprintf(3)をそのまま利用しています。

詳しくはドキュメントを見ていただくとして、よく使いそうなものをリストしておきます。

小数点(g):

str = "%.05g" %  10 #=> "10"     (.05gで小数以下5桁、#なしだと小数点以下を抑制)
str = "%#.05g" % 10 #=> "10.000" (.05gで小数以下5桁、#ありだと小数点以下を抑制しない)

正負符号(+):

str = "%+d" %  10  #=> "+10"     (dで10進整数、+記号で正負符号を追加)
str = "%-d" %  -10 #=> "-10"     (dで10進整数、+記号で正負符号を追加)

ゼロで埋める(0):

str = "%#010d" %  10 #=> "0000000010" (#010dで上位を0で埋める10桁)

文字コードを出力(c):

str = "%c" %  10   #=> "\\n" (cで10進数文字コードから文字を出力)
str = "%c" %  0x0a #=> "\\n" (cで16進数文字コードから文字を出力)

Rails / Ruby 界隈ウォッチ(2016/09/21)クールなHTMLエディタ「Mozilla Thimble」他

$
0
0

こんにちは、hachi8833です。

RailsやRuby界隈のニュースをピックアップしながらご紹介します。ニュースソースはそれほど固定しない感じでやっておりますので、Railsと関係ないこともあるかもしれませぬ。

Reddit.com

Microsoft Signature PCなLenovoでLinux動かないorz

いきなりRailsと関係ありませんが、「Microsoft Signature PC」なLenovoマシンがLinuxをインストールできないようになっているという残念なニュース。やり取りの魚拓もあります。

160921_1705_hc11ny

↑Fedoraで何とかしたい場合のUEFI Secure Bootの殺し方はFedora: Disabling UEFI Secure Bootにあるそうです。

RubyFlow

TextrisでSMSメッセージをメール同様に送信

SMSメッセージ送信や電話発信用Ruby gemといえばtwillio/twilio-rubyがstarを900個近く集めており、公式の日本語ドキュメントもあります。今回名乗りを上げているTextrisは、内部でtwillio/twilio-rubyを使いつつも(Twilioのアカウントが必要)、ActionMailerでのメール送信と同様の「Railsらしい方法で」SMSメッセージを送信できるのが売りだということです。Railsの新機能であるActive Jobでのジョブ管理もできるようです。

Brakeman Pro Engineリリース

静的な脆弱性解析ツールであるBrakemanにPro Engine版が登場し、Pro Desktop版の2つに製品を分けたとのことです。オープンソース版との比較リストを見ると、GUI関連の機能は当然ながらDesktop版が最も多く、Pro EngineはCIに組み込む目的でGUI的な機能を省略する代わりにレポート出力機能を充実させているようです。お値段はこちら

Qiitaに日本語記事がありますが、だいぶ前のものですね。

RabbitMQとHTTPとRailsでマイクロサービス

RailsというよりほとんどRabbitMQの解説ですね。RabbitMQはAMQP(Advanced Message Queuing Protocol)の実装のようです。昔の記事ですが、AMQPによるメッセージングがやや詳しいですね。

Ruby trunk

Module#aliasとModule#alias_methodのバグ

Ruby 2.1では正常だったModule#aliasModule#alias_methodが、Ruby 2.3.1で期待どおり動作しないという報告。

    module M
      def original ; puts __callee__ ; end
      alias_method :aliased, :original
    end
    class A
      include M
    end

    A.new.original
    #⇒ original
    A.new.aliased
    #⇒ aliased  (2.1の場合)
    #⇒ original (2.3.1の場合)

既存の#12176#11964との関連が報告されており、修正はまだの様子。

ところで、このhttps://bugs.ruby-lang.org/を掘ってみるとときどき面白いものが見つかりますね。Wikiの各種ドキュメントにまぎれてRubyistに必要なことというのを見つけました。チケットは英語のみかと思いきや日本語で上がってるのもちらほら。

Hacker News

pardonsnowden.org

「スノーデンに恩赦を」といういかにもHacker Newsで盛り上がりそうなサイト。Steve Wozniakがスノーデンを紛れもない英雄とまで呼んでいるとtickerに表示されてます。

ナードのための音楽理論

個人的にじわっときたのでメモ。「CメジャーとAマイナーって構成音がまったく同じなんだけどどうして両方要るんだ」=>エイリアスだと思えばよろし。

音楽理論は、プログラミングで言えば言語仕様やデザインパターンみたいなもので、理論を完全に理解しても曲を作れるようになるわけではないところがポイントかも。音楽理論は作曲家よりもアレンジャーにとって圧倒的に便利な道具で、作曲は音楽理論を全然知らなくてもできるけど、アレンジやオーケストレーションは理論なしではつらい。

ちなみに世界で最も多く売れたシングル「ホワイトクリスマス」を作曲したIrving Berlinは楽器どころか譜面も読めず、アシスタントが彼の歌を聴き取って譜面に起こしたんだそうで。

Let’s Encryptの運営コスト

暗号化なしのHTTP接続への風当たりが強くなる今日このごろ、無料で証明書を発行してくれるLets’ Encrypt(注: 日本語サービスもあり)が注目を集めています。yamasitaさんによれば既存の認証局とちゃんと棲み分けできているんだそうです。

そのLet’s Encrypt自らが運営コストの内訳を公開しており、2017年の予算はざっくり300万ドル、うち2/3は人件費。費用のほとんどを企業スポンサーからの寄付でまかなっているそうです。

こうまでしてもらった以上、暗号化なしのWebサービスを放置するわけにはいかなくなりました。私の持ってるサービスも早いとこHTTPSに移行しないと。

Mozilla Thimble

Mozilla謹製のWeb版HTML/CSS/JSエディタですが、驚きの完成度にしてデザインも見事。HTML/CSS/JSを学ぶ学生さんはもうこれしかないでしょう。正直、惚れた。

160921_1414_ge7EGB

ちなthimbleは「指ぬき」ですね。金属キャップ状の洋風指ぬきに対し、日本の指ぬきは革ベルト風。

western

japanese

Bash Shellの奥義集

Bashの珍しい技をいろいろ紹介しています。今度翻訳してみようかな。

子どもにはシェルの方がいいんじゃないか

話は違いますが、義務教育としてのプログラミング教育はもうシェルの基本機能だけ教えれば十分なのではないかという話題で社内でちょっと盛り上がりました。

たとえば単純なループひとつ取っても、子どもによっては越えられない壁になりえますし、ポインタだの黒魔術だのを無理強いしてプログラミング嫌いの子どもを大量生産しては元も子もありません。自分のやりたいことをただ並べて一気に実行するという最小限の自動化はたぶんいつの時代にも必要になると思いますし、一気に作業が完了するさまはプログラミングの快感の原点でもあります。それに一番近いのはシェル(スクリプト)でしょう。

つまんない罠やバッドノウハウやしがらみを極力排除した、教育用の極小シェルというものがあってもいいのかなと。プロのツールと、誰もが使うツールは同じにしない方がよいように思います。

ただ、そういうのを文科省とかが主導で制定すると絶望的にセンスないものができそう。むしろ子どもをたぶらかす魅了するノウハウを長年に渡って蓄積している玩具メーカー・ゲームメーカーが開発するといいのかも。子ども扱いするのではなく「俺今すげーことやってるぜ」感を演出する感じで。

160921_1508_rSBCGk

関連記事

Ruby/Rails界隈ウォッチ(2016/09/28)constantizeの注意点、GoのGUI “gallium”登場ほか

$
0
0

こんにちは、hachi8833です。今週も流浪のRuby/Rails界隈ウォッチです。

RubyFlow

160928_1638_XvIP4h

constantizeは使い所に注意

Rails3から導入されたActiveSupport::Inflector#constantizeは、Stringオブジェクトのメソッドとして呼び出すと指定の名前で定数を探せますが、クラスも定数であるがゆえにクラス名の文字列からクラスオブジェクトを得ることもでき、お便利に使われることが多いようです。

この記事ではconstantizeの乱用は危険であると警告し、絶対安全な使い方などないとまで言い切ったうえで、代替手段について解説しています。

記事末尾のmorimorihogeさんによるコメントもご覧ください。

Ruby Prize 2016

Rubyの新人賞であるRuby Prize 2016の候補者募集中とのお知らせ。ただし英語情報は少し遅れていて、日本語ページでは既に候補者が発表されています。ここから3名にまで絞り込まれ、受賞は11月のRuby World Conferenceで発表されます。

Bullshit-Free Review

160928_1639_vdl3Ju

Samesite cookieで「Cross-site timing attack」を防ぐ

SameSiteはChromeやOperaで試験的に導入されているcookieの新しい属性であり、これを指定したcookieはクロスサイトなリクエストに送信されなくなります。自サイトがあえてクロスオリジンなリソースを提供しているのでない限り、SameSite cookieは常に利用すべきと指摘しています。

cross-site timing attackは目新しい用語ですが、リンク先ではいわゆるCSRF(Cross-site request forgery)の一種であると説明されています。

Rails 5のActionCableとRethinkDBでスプレッドシートを作る

spreadsheet-full

Googleスプレッドシートでおなじみの、シート上のカーソル位置がダイナミックに共有される機能をRails 5のActionCableとRethinkDBで作ってみようという企画。RethinkDBはMongoDB的なデータストアですが、リアルタイムアプリに向いており、Ruby的な動的クエリ言語を装備しています。

Git bisect

バグの疑いがあるコミットを二分探索で高速検出するコマンドラインツールです(bisect=二等分)。

3分でわかるCSS Flexbox

Flexboxを非常に簡潔に解説しています。少し前に話題になったA Complete Guide to Flexboxの前に読むとよさそうです。Flexboxで噴出中のさまざまなバグも合わせてチェック。

ところで、こうした解説は図の描き方ひとつで大きく読みやすさが変わりますね。私たちはつい線画のボックスで何もかも描いてしまいがちですが、特にCSSのボックスモデルなどの説明ではこのように面と色で作図すると、読者の認知の負担がおおむね軽くなるように思います。

160928_1651_R0B7cQ

Ruby Weekly

160928_1641_BubfCD

このニュースサイトはまとまりがよいですね。

「Docker Composeによるオーケストレーション」が無料でダウンロード

英語ですがわずか19ページなのですぐ読めちゃいます。

Sidekiq 4.2で Rails 5をサポート

バックグラウンド処理でおなじみのSidekiqがRails 5に対応しました。Sinatraへの依存を解消してRackを直接使うようになったとあり、こっちの方が重要かもしれません。

少し前に話題になったKill Your Dependencyで相当メジャーなgemでも無駄なライブラリをインクルードしていることが指摘されていたのを思い出しました。個別のgemで重複するライブラリを機械的に解消するのは簡単ではなさそうですね。

HTTP APIで使うRESTとRPCの違いを理解する

RESTとRPCの違いを改めて確認するのによさそうです。コメント欄でMicrosoft のDarrel Miller氏がブログでRESTかRPCかは、URLとは関係ないと追記しています。

Ruby trunk

160928_1649_IkaWyb

#12790 stdlibクラスの#inspectを良くしたい

たとえばBigDecimalが返す#inspectの結果が生々しすぎて読みづらいというissueです。DateTimeなど他にも何とかして欲しいという意見も。

現状:

<BigDecimal:128d34f4,'0.25E2',9(18)

理想:

#<BigDecimal: 250> もしくはsig.digをそのまま表示
#<BigDecimal: 250 digits: 9(18)>
#<BigDecimal: 1.5E35> 大きい数値ならこれでもいい

#12788 #lstripと#stripを10倍速くしたった

Times before: 0.195159 and 1.918969

Times after: 0.013684 and 0.143966

So a bit more than 10x faster.

だそうです。

Hacker News

160928_1654_q6srdR

ripgrep

最速を謳って話題になっている新顔grepですが、むしろ「Unicodeフルサポートだぜ、常にオンだぜ」の方が重要だと思います。まだ試していませんが、さまざまなgrepツールで絵文字などのなるべく意地悪な文字をgrepしてみるといろいろわかって面白そうです。

Chromiumを脱Google化

Google寄りの機能を取っ払って透明性を高めたChromiumバリアントです。Starが1600個を超えています。

MITライセンスをきちんと読む

この種の法務文はほとんどの場合流し読みされてしまうものですが、英語日本語問わず、ライセンス条項のような文章をみっちりみっちり読む経験は一度しておいて損はないと思います。

関係ありませんが、義務教育で契約書の読み方・書き方といった単元がないのはおかしいとずっと以前から思っています

Github Trending

160928_1701_Q9dJIU

md2key

RubyKaigi 2016ので小会議室から人があふれるほど盛況だったDockerネタでおなじみのK0kubunさんがまた新しいの作ってます。markdownでkeynoteが書けるんだそうです。早速やってみよ。

その他

https://browser-issue-tracker-search.appspot.com/

主要なブラウザのissueを追いかけるのに便利なバグトラッカーです。

alexflint/gallium

160928_1703_BdFM8t

突然のGo言語で失礼します。GoとHTMLでデスクトップアプリケーションを書けると聞いて私カッとなって書いてしまいます。

alexflint/galliumは、Chromiumを使ってGoでデスクトップアプリをさらっと書けてしまう待望のアプリです。ファイルの履歴が10日足らずという信じがたい新しさにもかかわらず、既にStarが2500を超えているという、とてつもなく劇的な伸びようです。

Issueが現時点でわずか2件なのは新しさゆえでしょう。安定性などはこれからの課題ですね。

私、思えば今年の頭ぐらいからGo HTTPサーバーをElectronアプリに埋め込むという大変キモい作業をずっとやっておりましたが、即座に乗り換えを決意しました。ひとまず、手元でgo buildしたワンバイナリからサンプルのGUIが動くことまでは確認できました。

現在はMac版のみのようですが、星の多さとSlackのGophers#galliumの盛り上がりからしてWindows/Linux版も遠くないように思ったのは私の願望でしょうか。そしてこの作りであれば、Android/iOSアプリ化もそれほど困難ではない気がします。これまで弱点と言われ続けていたGoのデスクトップGUIですが、これで流れが変わるかもしれません。

今週は以上です。

morimorihogeコメント

#constantize を初めとしたリフレクション系のメソッドはユーザの入力パラメータを素通しするのは危険だよ、というのはRailsに限らずどんな言語でも注意しないといけないことかと思います。STI(Single Table Inheritance)を使ったフォームなんかを使う時には便利なので使うこともありますが、元記事の方でもあるように許可するクラスをどこかで定義してホワイトリスト許可するのが妥当な対策なのかなと思いました。

Ruby World Conferenceには今年も参加しますので、Ruby Prizeは楽しみですね。Ruby Prizeは実装に限らずRubyコミュニティに対する貢献が評価されるという珍しい賞なので、コミュニティに対する貢献を大事にするRubyコミュニティらしさが出ているのではないでしょうか。

Git bisectはGit標準ツールなので、知らなかったのであれば知っておくとバグ追跡でお世話になることもあるかもしれませんね。

Stop Cross-Site Timing Attacks with SameSite cookiesの件で言われている「Cross-Site Timing Attacks」についてはCSRFの亜種っぽいのは分かるのですが聞き慣れない単語なので具体的にどういうモノなのか、もうちょっと読んで把握してみたいと思います。まだ今一つ把握しきれていない(文中で言われる”cache”がどこでキャッシュされるものを指しているのかなどが読み取れない)ので、理解できたら解説してみようかなと思います。

他にも色々コメントしたかったのですがちょっと仕事の方で手が空かないので今日はこの辺で失礼します。

関連記事


Rails / Ruby 界隈ウォッチ(2016/10/05)Mac OS SierraとRubyの問題、Learning Gitほか

$
0
0

こんにちは、hachi8833です。10月最初のRuby/Rails界隈ウォッチです。

RubyFlow

160928_1638_XvIP4h

商用プロジェクトで使われているRubyのバージョン(2016年版)

詳しくはリンク先をご覧いただくとして、現行のプロジェクトではバージョン2.2.xと2.1.xで半数を超えていますね。1.9系も減りつつあるとはいえまだ10%を占めています。

新規プロジェクトはさすがに2.2.xと2.3.xで8割を超えています。新規で1.9系を使う例はごくごくわずかですが、どんな事情があるのでしょうか。

morimorihogeコメント

うーん、このリンク先のデータはsemaphoreというcontinuous development支援サービスのデータを参照しているみたいなのですが、今一つ信頼していいのか怪しく感じました。僕の感覚ではRuby 1.8系のzombieなアプリはもっと世の中にあるはずという印象です。
このsemaphoreというサービスがリリースされたのは2012年のようなので、その頃には既に新規でRuby 1.8系のサービスを作ることはほとんどなかったというのが影響しているのではないかと思いました。

Ruby on Railsの(に限らない)CORSへの対応について

Cross-Origin Resource Sharing(CORS)はW3Cが2014年にRecommendationとした、クライアントサイドで現在開いているページ以外のドメインへのアクセス(Cross-origin)を可能にする機能の仕様です。このためにAccess-Control-Allow-Originなどの新しいヘッダが使用されます。

この記事の著者も「CORSについて」という別記事を読んで初めてCORSが分かったと述べており、そちらを読んで欲しいとのことです。

ざっと見たところ、Railsの静的なassetファイルをCDN(Contents Delivery Network)に配置したときにassetがクロスオリジンになってしまう問題といくつかの解決方法について主に述べています。

CORSについてはMDNの日本語解説があります。

Bullshit-Free Review

160928_1639_vdl3Ju

Railsアプリ間でモデルを共有する

1台目のRailsアプリからconcernをgemとして切り出し、2台目のRailsアプリに導入するという手法を紹介しています。Part1とPart2に分かれている大作記事です。

morimorihogeコメント

個人的には複数app間でModelをsharingするのは地雷を踏みまくりそうなポイントだらけなので全くオススメできないですね。もしどうしてもやりたければGit submodule/subtreeとかでapp/models/#{namespace}を共有する、とかで確実に同じソースが共有されるようにしたいところですが、僕は地雷を踏み抜く自信があります(確信)。
おとなしくfat applicationにするか、microserviceに切り出すとかを考えた方が後々禍根を残さないんじゃないかなあと思いました。

Rubyで使える画像識別サービスAPIを比較する

機械学習系の話題です。大手デベロッパーからコミュニティまで、画像識別サービスを利用するさまざまなRuby gemを紹介しています。

詳しくはリンク先を読んでいただくとして、その中でGoogleがGoogle Couldプラットフォームを利用するためのgem「google-cloud」をリリースしていることを初めて知りました。Google Couldプラットフォームでは画像識別以外にもさまざまなサービスを利用できるようです。

こうした機能をgemで導入できるようになってきたことで、普通のRailsアプリでもだんだん使われるようになるかもしれません。

Ruby Weekly

160928_1641_BubfCD

月額固定費用でRailsアプリのメンテナンスを請け負うreinteractive

こちらは企業サイトの宣伝ページですが、月額固定費用でアプリをメンテナンスするというビジネスモデルがやや目新しく思えました。

morimorihogeコメント

サービスサイトを眺めてみましたが、バグフィックスとかsecurity updateみたいな機械的にやれる様なことだけ対応する様にもみえて、今一つどれくらいきちんとしたことをしてくれるのか分かりませんでした。これだけではなんとも言えないなあ。。。

Ruby trunk

160928_1649_IkaWyb

#12804 MacをSierraにアップグレードするとdbアクセス時にRailsコンソールが死ぬ

実際に死ぬのはSQLite3だそうです。

#12808 Mac OS SierraでRubyをビルドするとProcess::UPTIME定数が生成されない

この間リリースされたMac OS X Sierraでは/usr/include/time.hのCLOCK_UPTIMEがなくなってCLOCK_UPTIME_RAWになってしまったのだそうです。

Sierraではキー入力周りも変えられているらしく、Macのキーリマッピングソフトウェアの定番Karabinerが動かなくなって多くの人が困っています。私もです。

morimorihogeコメント

仕事用Macでは警戒してSierraにまだ手を出してない僕に問題はなかった(キリッ

Github/trending

pg-eyeball

PostgreSQLのexplainコマンドの出力を見やすく整形してくれるgemです。Go言語で書かれたPostgreSQLビジュアライザであるgocmdpevもインストールしておけば、さらに見やすくカラーリングできます。

Railsコンソールで次のようにpg-eyeballとgocmdpevを実行できます。Railsのバージョンは4と5に対応しているそうです。

User.all.preload(:profiles).eyeballs.gocmdpev

161005_1234_lrT4GA

GitHub Changelog Generator

GithubのChangelogをmarkdown形式で整えてくれるgemです。ドキュメント化を前提としたコミットメッセージを心がけていれば便利かもしれません。

161005_1429_pFjE7X

https://github.com/skywinder/github-changelog-generatorより

Hacker News

160928_1654_q6srdR

https://github.com/mxgmn/WaveFunctionCollapse

ビットマップでパターンを与えると、その特徴を捉えて類似のビットマップパターンを生成するというプログラムです。ゲームによくあるマップ自動生成みたいなものだと思いますが、動作がかなりインテリジェントで、2次元3次元を問わず、与えたパターンの特徴を壊さずにそれっぽいマップをずんずん生成します。3次元はさすがに重いそうです。

ゲームプログラミングのことはわかりませんが、これマジで凄いんじゃないでしょうか。もうマップ作成はこれだけでできちゃいそう。

C#で書かれていますがそれほどサイズは大きくないので移植すると楽しそうです。パターン例を見ているだけでも楽しくなります。

161005_1131_8CJF8x

161005_1140_OVF0Pp
https://github.com/mxgmn/WaveFunctionCollapseより

Github Trending

160928_1701_Q9dJIU

Gitの実験版「Gitless」

既にはてぶなどでも話題になり始めていますが、Gitのコマンドセットを縮小して使いやすさを目指したGitlessが登場しました。Pythonで書かれています。

Gitとの比較については、同ページのGitless vs. Gitを見るのが早いでしょう。

161005_1151_eZCypf
http://gitless.com/#vsより

その他

Learning Gitがいい

Gitは開発者の間に相当普及しましたが、コマンドが込み入っていたりバイナリやsubtreeの扱いが今ひとつだったりということもあって、DTPやデザイナーに使ってもらうにはまだ敷居が高い一面があることは皆様も感じていらっしゃるかと思います。

そういえば、昨日yamasitaさんに教えてもらったLearning Gitというサイトが徹底してビジュアライズされていて、非エンジニアにインタラクティブにイメージを掴んでもらうのによいのではないかと思いました。早くも日本語化されていて、以下のように日本語の品質も高いのでおすすめです。今週一番の拾い物はこれかもしれません。

161005_1204_upWzwY

solution

http://k.swd.cc/learnGitBranching-ja/より

DockerがInfraKitをリリース

クラウド各社ごとに異なっているDockerの運用を共通化・自動化するのが狙いのようです。将来はDocker Engineに取り込まれるとも。これが普及すればクラウドの切り替えがしやすくなるので、乗り換えキャンペーンが激しくなりそうです。

現時点ではGo環境を用意して自分でビルドする必要があります。遠からずaptやhomebrewで導入できるようになるのではないでしょうか。

ワンバイナリでHTTP/2とTLSとLet’s Encrypt認証が使えるHTTPサーバー「Armor」

Go言語のHTTPサーバー「echo」の作者がechoをベースに作ったワンバイナリのHTTPサーバーです。Let’s EncryptからTLS証明書を自動で導入してくれるそうです。弊社インフラエンジニアのyamasitaさんが押しています。

今週は以上です。

関連記事

[Ruby/Rails] strftimeのよく使うテンプレート

$
0
0

こんにちは、hachi8833です。つい先ほどTechRachoをSSL暗号化いたしました。

query

160914_1648_wKvt8f

関係ありませんが、スクショ撮影中にSlackの時間表示方法を切り替えました。

以下、よく使いそうなオプションを集めてみましたのでスニペットにでもどうぞ。strptimeはまた今度。

注意: コード中で時間取得に使っているTime.nowはすべてRuby 2.3.1の場合です。

RailsであればTime.zone.nowTime.currentにする必要があります。

strftime

Time#strftimeは、Timeオブジェクトの表示形式を指定して文字列に変換します。TimeはRubyの組み込みオブジェクトです。個別のパラメータについてはTime#strftimeをご覧ください。

「2016年10月06日 15:37:49」にしたいとき

time = Time.now
time.strftime("%Y年%m月%d日 %H:%M:%S")

161006_1538_gBs6L4

「16-10-06」にしたいとき

time.strftime("%y-%m-%d")

161006_1546_7BwmfC

「04:18 PM」にしたいとき

time.strftime("%I:%M %p")

161006_1625_3WLALN

「2016/10/06(木)」にしたいとき

以下はRailsのI18nを使わない方法で曜日を表示しています。タイムゾーンなどを正しく扱うには「Railsでの、日本語対応の短縮曜日の表示」などを参考にI18nをお使いください。

wd = ["日", "月", "火", "水", "木", "金", "土"]
time = Time.now
time.strftime("%Y/%m/%d(#{wd[time.wday]})")

161006_1615_WNjo6k

参考: 日本語曜日入り日付フォーマットを1行で書く

「午後 04:18」にしたいとき

RubyのTimeクラスに午前/午後を取得するメソッドがないので、以下の方法で「午前」「午後」を表示してみました。

time = Time.now
ampm = time.hour < 12 ? "午前" : "午後"
time.strftime("#{ampm} %I:%M")

161006_1830_OJvLgj

なお、昼の12時が午前か午後かについてはYahoo!知恵袋などに議論がありました。

参考: Ruby: how to get at meridian in Time objects?

関連記事

[Ruby/Rails] strptimeのよく使うテンプレート

$
0
0

こんにちは、hachi8833です。昨日のstrftimeテンプレート記事に続き、strptimeのよく使うオプションをテンプレート用にまとめてみました。

query

160914_1648_wKvt8f

注意: コード例はすべてRuby 2.3.1の場合です。

RailsであればActiveSupportを使うことが多いと思いますが、タイムゾーンの扱いに注意する必要があります。

参考: Rails4のタイムゾーン、時間周り、ActiveSupportの補足的なメモ

strptime

Time.strptimeは、日時を表す文字列をTimeオブジェクトに変換します。名前の「p」の由来は見つけられませんでしたが、parseのpではないかと推測しました。

Time.strptimeTimeクラスを拡張するRubyのライブラリなのでrequireして使います。昨日のstrftimeは組み込みのTimeクラスのメソッドですので、その点が異なります。

C言語のstrptime(3)やglibcを参考に作られています。

ParseDateモジュールでも同じようなことができます。

個別のパラメータについてはDate#strftimestrptime(3)をご覧ください。

Apacheログなどの「2016-10-07T04:05:06+09:00」を変換したいとき

Time.strptimeの例そのままですが、よく使われるパターンです。

require 'time'
Time.strptime('2016-10-07T04:05:06+09:00', '%Y-%m-%dT%H:%M:%S%z')

161007_1433_S2xwUk

「2016年10月07日 12:13:23」を変換したいとき

require 'time'
Time.strptime("2016年10月07日 12:13:23", '%Y年%m月%d日 %H:%M:%S')

161007_1217_aCp0Sj

ゼロがスペースになっている「2016年 1月 1日 1: 3: 3」を変換したいとき

require 'time'
Time.strptime("2016年 1月 1日  1: 3: 3", '%Y年 %m月 %d日 %H: %M: %S')

少々極端な例ですが、フォーマットの%mなどの前にスペースを置くことで、上位桁のゼロがスペースになっている文字列を変換できます。

161007_1229_47L2yj

スペースの部分に数字が入っても正常に処理されます。

参考: 日本語表記の日時をTimeオブジェクトに変換(Time.strptimeメソッド)

「2016-10-07 午後 04:18」を変換したいとき

「2016-10-07」の形式にはショートハンドの%Fが便利です。

午前と午後の表示は手を加える必要があります。めったに使わないと思いますが。

require 'time'
datetime = '2016-10-07 午後 04:18'.sub(/午前/, 'AM').sub(/午後/, 'PM')
pry(main)> Time.strptime(datetime, '%F %p %H:%M')

161007_1404_u1FGY0

なお、%p%Pでは同じ結果でした。

関連記事

[Ruby/Rails] 例外で深くなったネストをGuard Clauseですっきりさせる

$
0
0

こんにちは、hachi8833です。

161005_1727_4Wj7JB

Guard Clauseとは

Guard Clauseは、条件分岐のネストを深くしないための技法のひとつで、「ガード節」「ガード条件」などと訳されることがあります。その動作から早期復帰と呼ばれることもあります。

Guard Clauseの考え方を言葉で表せば、「引数が主に例外的な条件で例外的な値を返すのであれば、処理の冒頭部分で条件判断とreturnを行って例外処理を完結させ、メインの処理に影響を与えないようにする」ということになります。Rubyに限らず、多くのプログラミング言語のリファクタリングで有用な実装手法です。

始めはシンプルな例外処理であっても、改修が進むに連れて例外処理が深くなっていくことがよくあります。処理の分岐先の処理がどちらも同じぐらいの重みがあれば、通常どおり分岐するのが自然ですが、特に例外を事前にチェックするような処理であればGuard Clauseを積極的に使うことで条件分岐のネストを浅くでき、コードが読みやすくなります。事前処理する例外の数が多いほど効果を実感できるでしょう。

Rubyでは後置のifや後置のunlessが使えるので、以下のようにGuard Clauseを1行で簡潔に書くことができます。なお、後置のifはPythonやPerlなどでも利用できます。

#<略>
return if user.blank? #例外処理をここで完結させる

#メイン処理をここに書く
#<略>

Guard Clauseによるリファクタリングの例

リファクタリング前

def invalid_permission?(user)
  if user.present?  #<= この例外処理はGuard Clauseで書き直せる
    case user.permission
    when 1,2,3
      false
    else
      true
    end
  else
    true
  end
end

リファクタリング後

def invalid_permission?(user)
  return true if user.blank? #<= この1行で例外チェックをネストなしで完了できる

  case user.permission
  when 1,2,3
    false
  else
    true
  end
end

Guard Clauseの後は1行空けておくと、後から読む人に親切です。

morimorihogeコメント

処理の実装部分の書き方ってプログラマによって独自の癖があって見ていて面白いですよね。社内でもオブジェクト指向言語的に忠実に書こうとする人もいれば、考えた順番に書く人、Ruby的にlambdaとかを使って極力コードを短く済ます人など、個性が表れる部分だと思います。
ただ、どんな書き方であっても可読性は後々大事になってくる所なので、今回のGuard Clauseみたいな話はレビューで見つけたら指摘するようにしています。ただ、あまり細かく指摘しすぎても「レビュアーの書くコードと違うからダメ」みたいになって良くないので、直すべきレベルのものと個性で済ませられるもののさじ加減は難しい所ですね(それが行き過ぎるとレビュアー以外コード書けなくなるので)。

今回のコード例で言えば「否定型のメソッド」は直感的な理解を妨げるので僕は避ける宗派です(参考:Rubyにおけるunlessとコードの読みやすさについて)。
僕が書くとすると、#invalid_permission?ではなく#valid_permission?をメソッドとして実装し、利用側では

if invalid_permission?(user)
  # ...
end

ではなく

unless valid_permission?(user)
  # ...
end

の方が頭に入りやすいと思ったりもするのですが、これは多分好みの範囲な気がします。
他にも#present?に対する#blank?の様に、#valid_permission?を実装した上で逆の意味を持つ#invalid_permission?を

def invalid_permission?(user)
  !valid_permission?(user)
end

の様に宣言するなど、色々と言いたいことは出てくるのですが、これも多分好みとプロジェクトのポリシ次第な感じがします。

エンジニアにとって自分で考えて書いたソースコードというのは大なり小なりこだわりがあるものなので、レビューするときには「これは誰が見ても直した方が良い部分なのか?」を気にしつつコメントするようにしています。どんなこだわりがあろうとダメなコードをダメと言えないチームは腐っていると思うのですが、指摘するときには「クソコードを憎んでプログラマを憎まず」スタンスでありたいものです。

merge/pull request reviewベース開発を進めていく中では「言いたいことは言うが、お互いを仲間として尊重し合う」という空気感が大事だと思いますので、こういう言い方やニュアンスというのも少しは気にしていくと、良い開発チームになっていくのではないかと思いました。

関連記事

Rails / Ruby 界隈ウォッチ(2016/10/12)RubyのHashの詳細、RethinkDBの会社が終業ほか

$
0
0

こんにちは、hachi8833です。10月2週目のRails/Ruby界隈ウォッチいってみましょう。

SitePoint

161012_1024_D7bjhM

RubyのHashの詳細を理解する

RubyのHashの仕組みをかなり詳しく解説し、わざとダメなハッシュアルゴリズムを使ってよいアルゴリズムとのベンチマークと比較して見せてくれています。ダメなアルゴリズムではHashの項目数が増大するとてきめんに遅くなっています。

161012_1124_FHVhid

SitePointより

RubyFlow

160928_1638_XvIP4h

Cells gemTrailbrazer

161012_1638_wI46WP

Cellsは、最近のJavaScriptフレームワークでよく使われる「ビューコンポーネント」をRuby on Railsでも使えるようにするgemです。Githubリポジトリでも☆が2,600を超えていて勢いを感じさせます。

Cellsは、Trailbrazerというハイレベルアーキテクチャのオプションでもあります。こちらも☆が2,000近く付いています。詳しく見ていませんが、ビジネスロジックの分離などいろんなことができるようです。

Trb-Stack

http://trailblazer.to/より

テスト駆動開発で時間を無題にしないために

テスト駆動開発(TDD)の是非はすぐ宗教論争になってしまいますが、ここでは是非ではなく、TDDをボトムアップではなくトップダウン設計に沿って行うことを勧めています。詳しくは参考リンクを見て欲しいとのことです。

Ruby Weekly

160928_1641_BubfCD

Let The Asset Pipeline Die

とりとめのないエッセイなのでお暇な方向け。ただこのエッセイで言及されていた議論をきっかけに、Code of Conduct(CoC)の一種であるContributor Covenantの導入がRubyをはじめ多くのオープンソースコミュニティで議論されていることを知りました。Code of Conductは日本語にしにくい用語ですが、いわゆる「綱領」とか「何とか宣言」のような、契約書やライセンスなどとは別の文書です。

CoCの例としてRubyKaigi Anti Harassment Policyを見ていただくと雰囲気を掴めるかと思います。ソフトウェア開発に直接関連するわけではありませんが、プロジェクトのコードや企業のサイトなどにこうしたCoCを配置したりする事例が増えているようなので、知っておくとよいと思います。

参考: Contributor Code of Conductのメモ

Ruby trunk

160928_1649_IkaWyb

Onigmoの書記素クラスタ「/\X/」がunicode.orgのテストをパスしない

extended grapheme clusterというメタ文字列を初めて知りました。「書記素クラスタ」と訳されることもあるようです。Ruby 2.3.0: 正規表現の解説によると、\Xは複数の文字がひと続きになって初めて意味のある文字列(Unicode結合シーケンス)にマッチする、特殊なメタ文字であるとのことです。

Hacker News

160928_1654_q6srdR

RethinkDBの会社が営業終了

9月のRuby/Rails界隈ウォッチで紹介した記事でも使われていたRethinkDBの開発会社から営業終了のお知らせが出されました。今後はオープンソース化し、同じサイトで引き続き入手できるとのことです。Hacker Newsのトップでした。

App StoreからDashが外された

dash-256@2x

私も使っているMac用のドキュメント検索&スニペットアプリ「Dash」の作者のアカウントを個人用から会社用に移行したところ、アプリがApp Store上でClosedになってしまったとのことです。このためiOS版をApp Storeで配付できなくなってしまい、MacOS版はApp Storeの外で引き続きサポートするものの、できるだけ早く手順に沿ってライセンスを更新して欲しいとのことです。

hackernoon.com

hackernoon

最近登場したhackernoon.comは、Hacker Newsの写真が豊富になったような塩梅です。

Facebookが新しいJavaScriptパッケージマネージャ「Yarn」を公開

161012_1628_HsYHd6

既に日本語のニュースにも出始めていますが、表題のとおりです。他のコードを参照して実行しないようにしてあるなど、セキュリティにも配慮されているようです。動作にはNode.jsがインストールされている必要があります。yarnpkg/yarnリポジトリを見ると早くも☆が8,000近くになっており、期待のほどがうかがえます。

ブログにはnpm install -g yarnでインストールするのが簡単と書かれていますが、パッケージマネージャでパッケージマネージャをインストールするのは何となく気持ち悪いので、私の場合は公式のインストール方法でインストールしてみました。

Github Trending

160928_1701_Q9dJIU

Discourse: 掲示板・メーリングリスト

discourse

Ruby on Railsで開発された掲示板・チャット・メーリングソフトウェア「Discourse」です。☆が20,000件近くあり、非常に人気があります。著名なニュースサイトboingboing.netの掲示板でも使われています。

今週は以上です。

関連記事

Viewing all 1093 articles
Browse latest View live