アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

HABTMのテーブル作成方法

こんにちは、endoです。

今回は「HABTM」のテーブル作成の方法です。

「has_and__belongs_to_many」の多対多の関係性を頭文字で略語で表示しているものです。

発音はなんて発音されているのでしょうか。 自分は「ハブトゥム」って読んでいますが、どんな呼び方をしているのか気になります。 こんな呼び方があるよって方は、ぜひ教えてください!

さて、「HABTM」ですが、テーブル作成で便利に作成することができます。

rails g migration create_join_table_facility_prefecture facility prefecture

こんなファイルが出来上がります。

class CreateJoinTableFacilityPrefecture < ActiveRecord::Migration
  def change
    create_join_table :facilities, :prefectures do |t|
      # t.index [:facility_id, :prefecture_id]
      # t.index [:prefecture_id, :facility_id]
    end
  end
end

これでもいいのですが、foreign_keyに対して爪が甘いなと思います。

そこで、これを改造します。

class CreateJoinTableFacilityPrefecture < ActiveRecord::Migration
  def change
    create_join_table :facilities, :prefectures do |t|
      t.references :facility, index: true, foreign_key: true
      t.references :prefecture, index: true, foreign_key: true
      # t.index [:facility_id, :prefecture_id]
      # t.index [:prefecture_id, :facility_id]
    end
  end
end

なお、改造しなくてもrails5.1.1は下記のコマンドでいけます。

rails g migration create_join_table_facility_prefecture facility:references prefecture:references
class CreateJoinTableFacilityPrefecture < ActiveRecord::Migration[5.1]
  def change
    create_join_table :facilities, :prefectures do |t|
      t.references :facility, foreign_key: true
      t.references :prefecture, foreign_key: true
    end
  end
end

issue自体は下記で上がっていました。

create_join_table should include indexes and foreign key contraints

取り込まれて使用できるようになっております。

foreign_key好きが突っ込むよな!って思ったので、嬉しかったです。

アクトインディではHABTMについて語りたいエンジニアを募集しております。

メールの Subject が読めない

こんにちは、tahara です。

Rails でメールを送信するとログに次のような感じで出力されますよね。

Sent mail to user@example.com (8.6ms)
Date: Mon, 03 Oct 2016 14:32:16 +0900
To: user@example.com
Message-ID: <57f1ed60d1544_656931b0dc404e7@yarn.mail>
Subject: =?UTF-8?Q?Rails?=
 =?UTF-8?Q?_=E3=82=A8=E3=83=B3=E3=82=B8=E3=83=8B=E3=82=A2=E5=8B=9F=E9=9B=86=E4=B8=AD?=
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: base64

これ Subject が読なめないw

nkf にくわせてやるとデコードしてくれます。 シェルで nkf Enter ペースト Enter C-d です。

~% nkf
Subject: =?UTF-8?Q?Rails?=
 =?UTF-8?Q?_=E3=82=A8=E3=83=B3=E3=82=B8=E3=83=8B=E3=82=A2=E5=8B=9F=E9=9B=86=E4=B8=AD?=
Subject: Rails エンジニア募集中

まあ Rails コンソールからもできます。

[13] pry(main)> Mail.new(subject: <<EOT).subject
[13] pry(main)* =?UTF-8?Q?Rails?=
[13] pry(main)*  =?UTF-8?Q?_=E3=82=A8=E3=83=B3=E3=82=B8=E3=83=8B=E3=82=A2=E5=8B=9F=E9=9B=86=E4=B8=AD?=
[13] pry(main)* EOT
=> "Rails エンジニア募集中 "

メールの Subject 読めました。

RubyKaigi2016 3日目レポート

こんにちは、endoです。

3日目のレポートになります。

ホテルの感想

まずはホテルの感想から始めます。

食堂が刑務所みたいな雰囲気を感じ、個人的には好きでした。 初日はwifiが繋がらない部屋に当たり、すぐさまフロントに電話をして部屋の移動を願い出ました。

なお、同じ階の部屋移動するだけでwifiが繋がるようになりました。 なんだったんだ、あの部屋は・・・

ホテルのフロントの方の対応が良く、満足しました。 トラブル起きた時の対応が親切だと、よかったなって思えますね。

では、レポートを開始します。

Ruby Committers vs the World

Ruby Committersの質疑応答

gitに移行しないの?

redminesvnが連携しており、それを紐解いていくほどの効果が見受けられない。 実際にCommiterはgitで運用をしており、現状での管理に問題があるとは認識していない。

Python3のリリースはどう思いますか?

互換性を保つようにしたい 見習うところはあるので、そこは見習うようにする

rbenvのような機能は?

rbenvはrubyの外側なので、rubyに入っても嬉しくないと思う

Ruby3x3: How are we going to measure 3x?

発表者:Matthew Gaudet

正しいベンチマークの取り方

CPU・温度によっても変化する。 タイポで早くなったと勘違いすることがある。

High Tech Seat in mruby

発表者:Yurie Yamane

mrubyでウォッシュレットを作る

状態遷移は開始位置によって、結果が異なったりする。 ロゴブロックでデモをしてくれました。 ガチの組み込み系の話でした。

It’s More Fun to Compute

発表者:Julian Cheal

rubyで音楽を奏でる

rspecの結果により、音を出したり出さなかったりして、メロディーを奏でる その他にもアルゴリズムで音楽を作成していました。

Optimizing Ruby

発表者:Urabe, Shyouhei

rubyの処理速度を早くする

メソッド実行時に処理の最適化がされていない部分がある。 最適化できる部分は最適化をして、処理速度を早めた。

Dive into CRuby

発表者:NARUSE, Yui

Crubyへの関わり方

新機能(メソッドの追加や既存メソッドの拡張)、最適化、トラブルシューティング補助などがある。

新機能は必要?

rubyにtouchを入れてほしいという要望があった。 ファイルの更新時刻を変更したいからです。 touchには次のような効果があります。

  • ファイルの更新時刻を修正する
  • ファイルを作成する

touchだと、余計な機能が入るのでお互い不幸になるという話でした。

感想

自分は初参加でしたが、普段話すことはないだろうエンジニアの方たちと交流ができて楽しかったです。

コードについては、rubyの仕組みの部分が大きく占めていたので、調べておけばよかったなと思ってます。 単純に書くだけではなく、なぜ必要になったのかの背景があるとメソッドの使う場面がわかりやすくなると思うので、言語の部分を今後は学んでいきたいと思います。

英語はエンジニアにとって必須科目のようなものなので、ここは普段からなんとかしたい・・・orz

Ruby会議に参加してから、OSSに貢献してみようかな?と思い、gem作ったり、使用したgemにpull reqを送るようになりました。 自分の中でプログラミングに関わる意識の変化があったので、参加してよかったです!

補足

現在では公式サイトから講演が見ることができます。 参加することができなかった人や、もう一度聞きたいという方にはピッタリですね。

RubyKaigi2016 2日目レポート

こんにちは、kawaguchiです。
2日目レポートをお送りいたします。

開場直後、企業ブースの様子

2日目のendoさんの様子です rubykaigiのスポンサーになった企業は、企業ブースという部屋で自社の宣伝ができます。
11時くらい以降に行くと企業の担当者がいらっしゃるので話をすることができるのですが、朝早いと担当者がまだ到着していません。

担当者不在をいいことに写真をたくさんとってきました。

会場の様子

机には電源コンセントが埋め込まれていました。

会場限定ガチャ

2回分のコインを投入したのですが、よくわからない缶バッチがあたったので3回目はやりませんでした。

昼ごはん

お昼になるとお弁当の配布が始まります。運営の角谷さんがお弁当の手渡しをしておりました。
お弁当は室内でも食べれるのですが外でも食べることができます。

無限コーヒー

企業ブースには、コーヒーポットとスポンサーによるお菓子が並んでおりました。
ありがたく頂戴しました。

行ってきましたよ、高倉二条に

感想

自分の観測範囲外にあるRubyを知ることができて大変興味深かったです。 さっそく東京に戻ってからrubyメーリングリストに登録しました。

最後に宿泊所の夕食で食べたトマトの写真を貼って終わりにしたいと思います。

以上です。

RubyKaigi初日レポート

こんにちは、endoです。

今回は「RubyKaigi2016」に参加したレポートになります。 当社では、RubyKaigiの費用の「チケット代」「交通費」「宿泊費」「懇親会」は全て会社で負担していただきました。 このような対応をしていただいた会社と、出張している間に業務を行ってくれたチームメンバーに感謝です!

では、初日のレポートを行っていきます。 なお、講演は英語が多く、内容を把握するのに苦戦しました(´・ω・`)

英語は重要だ・・・orz

Ruby3 Typing

発表者:Yukihiro “Matz” Matsumoto

Ruby3の目指す方向性

  • パフォーマンス
  • 並列処理

今回はこの中でも「型」についてのお話でした。

ダックタイピング

Rubyにはダックタイピングと呼ばれる考え方があります。 「アヒルのように歩き、アヒルのように鳴くものはアヒルに違いない」という考え方です。 ダックタイピングは柔軟性が高く、期待される振る舞いのみを考えればいいです。 期待される行動は、自分たちの頭の中にあります。

動的型言語のデメリット

実行するまでエラーかどうかがわからない。 エラーメッセージが親切ではない。 エラーが起こるかどうかわからないので、テストでカバーするようになっている。 静的型言語はメソッドに型が書かれているので、どのような値が必要かどうかがわかる。

型を導入する方法

型はほしいけど、型を記入することは避けたい。 現状の型推論ではない方法での、型推論を導入する。 100%の精度はできないが、0→80%までの精度になれば、ないよりはマシになる。 失敗した場合は、元に戻せばいい。

リリース時期

ケネディ大統領が月に行くという目標を定めてから、実現した。 目標は必要。 東京オリンピックが始まる頃にはリリースしておきたい。

dRuby in the last century.

発表者:Masatoshi SEKI

RubyとWebをつなぐ

HTTPをアプリに埋め込むことを楽しんでいた。 RubyとWebをつなぐ作業をしていて、翻訳作業をすることが嫌になってきた。

dRubyの紹介

分散オブジェクトシステム プロセス越しにメソッドが呼べる プロセス間でオブジェクトが送れる

Welcome to haconiwa - the (m)Ruby on Container

発表者:Uchio KONDO

haconiwa

mRubyで作成したコンテナ技術 もともとはCRubyで作っていたがsyscallsの限界があり、mRubyに書き換えた。

haconiwaを作った背景

docker/lxcでバグに遭遇したが、なかなか理解できなかった。 コンテナ技術を理解するためにhaconiwaを作成。

A proposal of new concurrency model for Ruby 3

発表者:Koichi Sasada

rubyの並列処理について

rubyの並列処理はGVL(Giant VM Lock)の関係でI/O待ちが発生している このため、rubyの並列処理は遅いということがよく言われる

guild

rubyの並列処理を早くするための新しい概念 GVLを解放することで、並列処理を早くするようにする

Isomorphic web programming in Ruby

発表者:Yoh Osaki

railsでreact likeに書けるようにする

jsが嫌いなので、rubyでreactを使いたいということで、作成 デモ講演を披露してくれました

Scalable job queue system built with Docker

発表者:Takashi Kokubun

Job Queueシステムを作成

カジュアルにJobが実行されていて、一元管理ができていなかった。 一元管理をするために、新しいJob Queueシステムを作成した

懇親会

この後は懇親会がありました。 個人的には海外の参加者の方と話をしてみようと思い、海外の参加者の方に話しかけていました。 ただ、日本語が普通に喋れる方だったので、日本語で会話をしていましたorz

海外の参加者の方との交流も図れるのがいいですね!

ちなみに自分がお話をした海外の参加者の方は、普段使う言語がPython・Goでした(`・ω・´)

こういう方でも参加しているのに驚きました。

初日感想

ノベルティが配布され、自分はステッカーを漁りまくっていました。 ブースではコーヒーが飲み放題で、交流も図れるので情報交換ができました。 このような対応していただいたスタッフの皆様に感謝です!

コミッターの方々は当たり前のように英語で話をするので、レベル差を感じました。 なんで英語そんなにできるんだ・・・

あと、見ている層が違うんだなーと感じた1日でした。

現場からは以上です。

iko-yo.netをruby2.3.1にアップグレードしました

kawaguchiです。

本番サーバのRubyを2.1.0から2.3.1にアップグレードしたことで変わったことについて書いていきます。

CPU

昼間はdeployによる変動が大きいので夜間の時間帯を切り取っています。 アクセス解析を見たところ、比較した時間帯のアクセスは同じくらいでした。

CPU使用率の平均が370から210へ下がりました。

2.1.0

2.3.1

レスポンスタイム

281msから262msへ下がりました。

2.1.0

2.3.1

まとめ

すごい

Rubyでなにもしない

こんにちは、chibaです!
最近、文字列を場合に応じてUTF-8(デフォルト)と、sjisに切り換えて文字を生成したいということがありました。
自分としては、

"こんにちは".send(if sjis? then :tosjis else なにもしない end)

と書きたかったのですが、Rubyでなにもしないメソッドってなんだったかなーと探してもなかなか見付かりません。 Haskellでいうid、LISP系では、identityというのが多いのですが、ruby identityでググったら、

  • Ruby 1.9 - Feature #841: Object#self - Ruby Issue Tracking System
    という一連のスレッドがみつかりました。
    なるほど、提案はされているもののリジェクトされてるんですね。
    高階手続きに馴染んでいる人ならば、identityの有用性は体験していると思うのですが、馴染みのない人からは、identityみたいに何もしないでそのまま受け取った値を返すものなんて何に使うの?という意見は割とFAQかなと思います。
    この議論中で
class Object
  def identity() self; end
end

というのが例として挙げられていました。これを使えば、

"こんにちは".send(if sjis? then :tosjis else :identity end)

"こんにちは".send(sjis? ? :tosjis : :identity)

と書ける訳ですね。
それで結局自分はどうしたかというと、Objectにメソッドを定義するのも気が引けたので

str = "こんにちは"
if sjis? then
  str.tosjis
else
  str
end

とか、

str = "こんにちは"
sjis? ? str.tosjis : str

と書くことにしました。
これはこれで妥当ですね。 ■

CMYK

こんにちは!! tahara です。 今回は Lisp on Rails はお休みで、Ruby on Rails の Paperclip の話題です。

IE で RGB の画像は表示できますが、CMYK の画像は表示できません。 CMYK から RGB に変換する手もありますが、変換時に結構色が変ってしまいます。 ということでアップロードする画像が CMYK の場合は、 バリデーションではじくようにします。

まず CMYK の判定ですが、ImageMagic の identify コマンドで可能です。

~% identify -format '%[colorspace]' ~/archive/normal.jpg
CMYK
~% identify -format '%[colorspace]' ~/archive/normal-rgb.jpg
RGB

ただし古い ImageMagic では -format '%[colorspace]' オプションが認識されないので -verbose オプションを使います。

~% identify -verbose ~/archive/normal.jpg
Image: /home/ancient/archive/normal.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Class: DirectClass
  Geometry: 290x200+0+0
  Resolution: 72x72
  Print size: 4.02778x2.77778
  Units: PixelsPerInch
  Type: ColorSeparation
  Endianess: Undefined
  Colorspace: CMYK      <=== これ!!
  Depth: 8-bit
  ...

この identify を呼び出して CMYK をチェックするバリデーションを config/initializers/paperclip.rb に組み込みます。

module Paperclip
  module ClassMethods
    ...

    # CMYKIE で表示できないため、検証でエラーとする。
    def validates_attachment_not_cmyk name, options = {}
      message = options[:message] || "CMYK フォーマットの画像はブラウザによって表示できないため使用できません。お手数ですが RGB フォーマットに変換してください。"
      attachment_definitions[name][:validations][:not_cmyk] = lambda do |attachment, instance|
        original_file = attachment.instance_variable_get(:@queued_for_write)[:original]
        colorspace =
          begin
            attachment.file? && original_file &&
              Paperclip.run("identify", "-verbose #{original_file.path}")
          rescue
            nil
          end
        if colorspace && colorspace =~ /^\s*Colorspace: CMYK$/
          message
        end
      end
    end
    ....

これでモデルから validates_attachment_not_cmyk というひどい名前のバリデーションが使えるようになります。

  validates_attachment_not_cmyk :picture_1

まとめるとこうなります。

(incf ImageMagic)
(decf IE most-positive-fixnum)

テストを通らないリリースを止めるライブラリ

昼にキリンフリーを飲むと機嫌が良くなる火曜日担当のkomagataです。

rspecのテストが通らないとデプロイを止めてしまうcapistranoのレシピのgemを作りました。

showstopper 0.1.0

ShowStopper is capistrano recipe that stop deploy when rspec is red.

インストール

$ sudo gem install showstopper -s http://gemcutter.org

Capfileの中で読み込むだけで設定完了です。

$ vi Capfile
(...)
require 'showstopper'

これでrspecが通ってないのに誰かがデプロイしようとすると・・・

% cap deploy
(...)
  * == Currently executing `deploy'
    triggering before callbacks for `deploy'
  * == Currently executing `deploy:spec'
    rspec test failed

showstopperがデプロイを中止してしまいます!

これを投入していい加減なテストのあるプロジェクトを恐怖のどん底に陥れてやりましょう!