RubyMineからVimへ少しずつ移行中

こんにちは。beaglesoftの真鍋です。

昨年は試行錯誤の年でしたが今年は挑戦の年としたいと思います。どうぞ今年もよろしくお願いいたします。

さて、昨年の終わり頃からRuby on Railsをいじっています。あわせてVimで開発もトライしていて結構いい感じに使えそうだということがわかってきました。

ただ、忙しいタイミングではまだRubyMineのほうが早く開発ができるので併用している感じです。(なんで今さらVimなのかについてはまた別な機会にまとめたいと思います。)

そんな感じでVimを利用するようになったせいで、キーボードも変えました。もともとはRealforceの日本語キーボードを愛用していたのですが、今はHHKBの英語キーボードを利用しています。

最初はかなり戸惑ったのですが、最近はRealforceよりもこちらのほうがいい感じになっています。

PFU Happy Hacking Keyboard Professional2 Type-S 白(英語配列)

PFU Happy Hacking Keyboard Professional2 Type-S 白(英語配列)

ショートカット

Vimを使うようになってから結構ショートカットキーが気になりだしてきました。RubyMineで開発していてもたいていのコマンドはターミナルを利用することが多くなってきていて、ターミナルをいかに起動するかということは結構気にしています。

これまでは普通にマウスでポチッとクリックしてターミナルウィンドウを開いたりAlt+Tabでターミナルへ画面を切り替えたりしていたのですが流石に面倒になってきました。

そこで、RubyMineの設定でターミナルにショートカットを割り当てられないかと考えたのですが、もともとわ当てられていました。

デフォルトで割り当てられていたショートカットキーはAlt+F12でした。

ところが、まだ慣れていないせいかもしれませんがこれは辛い。なぜならいま利用しているキーボードはHHKBだからです。

HHKBではファンクションキーはFn+数字キーの組み合わせになるのです。

慣れている方には平気かもしれませんが、矢印キーはいいとしてもファンクションキーとAltキーの組み合わせはぱっとできるものではないです。

ということで、早速キーの割り当てを変更するようにしました。

Alt+4を割り当てる

RubyMineのショートカットキーは簡単に変更できます。

File -> Settings -> Kyemap

ここを開くことでキーマップを変更できます。今回はTerminalを変更したいので検索ウィンドウにterminalを入力して右側のキーのあたりで右クリックしてAdd keybord Shortcutを選択します。

あとは変更したいキーをタイプすれば変更が確定できます。

さいごに

環境を変えることはいろいろと勇気のいることです。特に私のようにVisualStudioやIntelliJが中心な生活を10年以上送ってきた人間からするとVimというエディタが開発環境になるということはとても不思議な気がします。

RubyMineは多機能で素敵なIDEですし、今後も利用し続けると思うのですが今年はVimへの移行を少しずつしていきたいと思います。

deviseでメール認証済みなユーザーを作成する

こんにちは。beaglesoftの真鍋です。

deviseでテストユーザーを作成するときなどユーザーを認証済み状態にして確認メールを送信したくないときが結構あったりします。特に大量のユーザーアカウントを作成してテストをシたい時とかですね。

そんな時にどうするかということを少し調べましが、以下のAPIを利用すると実現できました。

user.skip_confirmation!

# 追記:こちらはメール送信は行わないが認証済み状態とならない
user.skip_confirmation_notification!

追記

ちょっと間違えていました。skip_confirmation_notificationはメールの送信は行わないというだけで認証済み状態とはなりませんでした。

Method: Devise::Models::Confirmable#skip_confirmation_notification! — Documentation for plataformatec/devise (3-stable)

利用環境

今回の利用環境は以下のとおりとなります。

$ ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux]

$ bundle list | grep devise
  * devise (4.2.0)
  * devise-bootstrap-views (0.0.10)
  * devise_invitable (1.7.0)

FactoryGirlを利用してみる

これがどのように便利かというとFactoryGirlを利用してテストデータを作成するときなどはとても便利です。なにせ、メールの送信を行う場合にはメールアドレスが存在する必要があることもあり、いろいろと手間です。

次のようにuserを生成します。ポイントはコールバックを利用してユーザーの作成前に上記のAPIを実行していることです。

# spec/factories/users.rb
FactoryGirl.define do
  factory :user do
    sequence(:email) {|n|  "test+#{Time.now.to_f}@beaglesoft.net"}
    password 'aaaaaaA@'
    password_confirmation 'aaaaaaA@'
    association :contractant

    before(:create){ |user|
      # ここで認証済みでメールを送信しない設定を行う
      user.skip_confirmation_notification!
      user.skip_confirmation!

    }
  end
end

実行するとこのような感じになります。

>> u = FactoryGirl.create(:user)
   (0.2ms)  BEGIN
  SQL (0.3ms)  INSERT INTO "service_plans" ("service_plan_name", "service_start_date", "service_end_date", "lock_version", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["service_plan_name", "basic"], ["service_start_date", "2016-12-25"], ["service_end_date", "2016-12-25"], ["lock_version", 1], ["created_at", "2016-12-31 21:53:54.742763"], ["updated_at", "2016-12-31 21:53:54.742763"]]
   (1.1ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "contracts" ("service_plan_id", "trial_term_expired_date", "user_status", "payment_customer_id", "lock_version", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["service_plan_id", 105], ["trial_term_expired_date", "2016-12-25"], ["user_status", 1], ["payment_customer_id", "MyString"], ["lock_version", 1], ["created_at", "2016-12-31 21:53:54.748693"], ["updated_at", "2016-12-31 21:53:54.748693"]]
   (1.0ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "contractants" ("contractant_name", "contractant_name_kana", "contract_id", "person_in_charge_name", "phone_number", "fax_number", "pref_code", "city_name", "town_name", "street_name", "building_name", "billing_no", "email", "contract_start_date", "lock_version", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING "id"  [["contractant_name", "テスト契約者"], ["contractant_name_kana", "テストケイヤクシャ"], ["contract_id", 102], ["person_in_charge_name", "田島 仁希"], ["phone_number", "090-9125-2709"], ["fax_number", "070-8496-5025"], ["pref_code", "30"], ["city_name", "福島市"], ["town_name", "茗荷沢新田"], ["street_name", "1-1-1"], ["building_name", "テスト建物"], ["billing_no", "1111111-2222222-333333"], ["email", "adan@collinsbatz.net"], ["contract_start_date", "2016-11-30"], ["lock_version", 1], ["created_at", "2016-12-31 21:53:54.752141"], ["updated_at", "2016-12-31 21:53:54.752141"]]
   (1.0ms)  COMMIT
   (0.2ms)  BEGIN
  User Exists (0.6ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = 'test+1483188834.6317208@beaglesoft.net' LIMIT 1
  SQL (0.4ms)  INSERT INTO "users" ("email", "encrypted_password", "contractant_id", "confirmed_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["email", "test+1483188834.6317208@beaglesoft.net"], ["encrypted_password", "$2a$11$UR6vwsMzgO3BrgBVXDdxtuy2lsJvrE9LCfljKJh6HkmBdrtLkSeAa"], ["contractant_id", 102], ["confirmed_at", "2016-12-31 21:53:54.755272"], ["created_at", "2016-12-31 21:53:54.766156"], ["updated_at", "2016-12-31 21:53:54.766156"]]
#<User id: 102, email: "test+1483188834.6317208@beaglesoft.net", created_at: "2016-12-31 12:53:54", updated_at: "2016-12-31 12:53:54", contractant_id: 102>
   (1.2ms)  COMMIT
>> u.confirmed?
true

この通り確認メールを送信する必要がなくなるので、テストデータを作成するときにメールアドレスの存在を意識する必要がなくなります。

JPAでLocalDateとLocalDateTimeを利用する

JPAでLocalDateTimeまたはLocalDateを利用するためには、以下のコンバータークラスを作成するだけで利用可能となります。(autoApply = trueを設定することでエンティティのフィールドに設定などは必要ありません。)

java.sql.DateとLocalDateの変換

java.sql.DateとLocalDateの変換処理を行うためのコンバーターを作成します。LocalDateはデータベースのDate型に対応します。

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.time.LocalDate;

@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<LocalDate,  java.sql.Date> {

    @Override
    public java.sql.Date convertToDatabaseColumn(LocalDate localDateTime) {
        return (localDateTime == null ? null : java.sql.Date.valueOf(localDateTime));
    }

    @Override
    public LocalDate convertToEntityAttribute(java.sql.Date  date) {
        return (date == null ? null : date.toLocalDate());
    }
}

java.sql.TimeとLocalDateTimeの変換

java.sql.TimeとLocalDateTimeの変換処理を行うためのコンバーターを作成します。LocalDateTimeはデータベースのTimestamp型に対応します。

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime,  java.sql.Timestamp> {

    @Override
    public java.sql.Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {
        return (localDateTime == null ? null : java.sql.Timestamp.valueOf(localDateTime));
    }

    @Override
    public LocalDateTime convertToEntityAttribute(java.sql.Timestamp  timestamp) {
        return (timestamp == null ? null : timestamp.toLocalDateTime());
    }
}

これでLocalDateとLocalDateTimeをエンティティに利用できるようになります。