波打際のブログさん

主に、プログラミング備忘録など。

論理削除Gem、 Kakurenbo をアップデートしました。

様々なわけがあってkakurenboは非推奨です。新規のプロジェクトではkakurenbo-putiの使用をおすすめします。

Kakurenboとは

 Rails4で論理削除を実現するためのGemです。実装に至った経緯は Rails4と3で論理削除を行うためのGem Kakurenbo の紹介と今更論理削除Gemを実装した理由。 - 波打際のブログさん を見てください。

アップデート

 今回のアップデートの目的は、ActiveRecord4.0.2以降との親和性を向上させることにあります。主な変更点は次のとおりです。

メソッド名のコンフリクト解消

 yusabana (Yuji Takaesu) · GitHub さんから、 destroy! メソッドのコンフリクト修正とRspec3対応のプルリクエストをいただき、マージしました。

 従来の Kakurenbo で物理削除を行う場合、物理削除用のメソッド destroy! を呼び出していました。しかし、Rails4.0.2にdestroy!メソッドが追加されたため、メソッドがコンフリクトしてしまいました。解決策として、物理削除のメソッドを廃止してオプションで物理削除を指定する設計に変更しました。

 この変更に伴い全ての物理削除メソッドを廃止し、オプションで物理削除を指定する設計に変更しました。

リレーショナルの論理削除に完全対応

 従来の Kakurenbo はリレーショナルの論理削除に一部未対応でしたが、今回のアップデートで完全対応しました。

Rails3サポートの打ち切り

 Rails4の対応に十分な時間を割り当てるために0.2以降のバージョンでは、Rails3の対応を打ち切ります。

アソシエーションの強化(7月23日追記)

 belongs_toやhas_manyなどでレコードに関連付けされた他テーブルのレコードの読み込みを、近日リリース予定のバージョン0.2.1で強化します。具体的には、読み込み元のレコードが論理削除されていた場合に、関連付けされたレコードのスコープに依存削除されたレコードを含めるようにします。(完全対応はRails4.1以降のみで、Rails4.0.xではThroughアソシエーションには未対応となります。)

リファレンス

 今回のアップデートで Kakurenbo のインターフェイスは次のようになりました。

論理削除

 Railsの削除メソッド全てが論理削除に置き換えられます。

# コールバックあり
model.destroy
model.destroy!

Model.destroy_all(hoge: 'fuga')
Model.where(hoge: 'fuga').destroy_all

# コールバックなし
model.delete

Model.delete_all(foo: 'bar')
Model.where(foo: 'bar').delete_all
復元

 destroy!メソッドの挙動に合わせてrestore!メソッドを修正しました。コールバックなどで復元がキャンセルされた場合に例外が発生するようになります。

# コールバックあり
# before_restore, after_restore コールバックが利用可能です。
model.restore
model.restore!

Model.where(hoge: 'fuga').restore_all
物理削除

 物理削除は、削除系のメソッドにオプションで指定するようになりました。

# コールバックあり
model.destroy(hard: true)
model.destroy!(hard: true)

Model.destroy_all(hoge: 'fuga', hard: true)
Model.where(hoge: 'fuga').destroy_all(nil, hard: true)

# コールバックなし
model.delete(hard: true)

Model.delete_all(foo: 'bar', hard: true)
Model.where(foo: 'bar').delete_all(nil, hard: true)

 その他のメソッドや使い方は alfa-jpn/kakurenbo · GitHub を確認してください。

謝辞

 今回のアップデートに関して、プルリクエスト、バグレポートを送信していただいた下記の方々に心より御礼申し上げます。

Rails4のバリデータをテストまでしっかり書いた備忘録

はじめに

 Rails4には様々なバリデータが用意されていますが、プロダクトを実装する過程で自作のバリデータを定義して使いたくなることが稀によくあります。稀によくある事なので、その都度使い方を調べていていますが、バリデータの実装からロケールファイルの定義、テストの書き方までまとまっているページがないので備忘録程度にまとめておきます。

バリデータ

今回作るバリデータについて

 バリデーション対象のカラムの内容が hoge であるかチェックするHogeValidatorを作成します。バリデーションのオプションで hoge が連続する回数を指定できるようにします。

# text が `hoge` であることのバリデーション
validates :text, :hoge => {:count => 1}

# text が `hogehoge` であることのバリデーション
validates :text, :hoge => {:count => 2}


こんな感じで使えるバリデータを作ります。

バリデータの定義

 `app/validators` フォルダに `hoge_validator.rb` を作ります。

class HogeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless ('hoge' * options[:count]) == value
      record.errors.add(attribute, :hoge, options)
    end
  end
end

ロケールの定義

 通常のバリデーションエラーメッセージと同様に記述していきます。

ja:
  activerecord:
    errors:
      messages:
        hoge: 'hoge成分が足りません。'

テスト

 `spec/validators/` フォルダに `hoge_validator_spec.rb` を作ります。

require 'spec_helper'

describe HogeValidator do
  let :validator do
    HogeValidator.new({:attributes => [attribute]}, :count => 1)
  end

  let :errors do
    ActiveModel::Errors.new(mock_class)
  end

  let :attribute do
    :text
  end

  let :mock_class do
    double('model').tap do |mock|
      allow(mock).to receive(:class) { ActiveRecord::Base }
      allow(mock).to receive(:errors) {errors}
      allow(mock).to receive(:read_attribute_for_validation) {attribute_value}
    end
  end

  subject do
    validator.validate_each(mock_class, attribute, attribute_value)
    errors.empty?
  end

  context 'ただしくHogeってる時' do
    let :attribute_value do
      'hoge'
    end

    it 'バリデーションが通ること' do
      expect(subject).to be_truthy
    end
  end

  context 'Hogeってないとき' do
    let :attribute_value do
      'fuga'
    end

    it 'バリデーションが通らない' do
      expect(subject).to be_falsey
    end
  end
end

 今回は省略しましたが、エラーメッセージに関するテストを行うとさらに良いと思います。

クラウドIDEを使ってみた Nitrous.io & Codeanywhere

はじめに

 お久しぶりです。昨年末から関ってきた某プロジェクトを5月にリリースし、最近やっと落ち着いてきました。落ち着いてきたついでに先週末ごろから開発環境を0から作り直しているのですが、開発環境の構築って面倒くさいですよね。検証環境なんかはVagrantを使えば良いかもしれません、しかし、開発環境となると話は別です。IDEをインストールしてエディタの設定をして...etc 面倒くささの極み!!!

そこで、私の中で今流行のクラウドIDEを使ってみることにしました。

クラウドIDE

 クラウド上の仮想マシンで、ブラウザから動作するIDEを使いソフトウェア開発ができる便利っ子です。今回は Codeanywhere と Nitrous.io を実際に使用してみました。

Nitrous.io

https://www.nitrous.io/
f:id:alfa-jpn:20140701034142p:plain

 上記の2つのサービスはウェブ上(HTML5)で動作するため、手持ちのSurfaceRTでも動作しました。

比較

 双方一番安い有料プランに登録しての比較です。
 

仮想環境について

Codeanywhere
  • Redhat
  • sudo権限あり
  • ブラウザ上のターミナル以外から接続する方法なし
Nitrous.io
  • Debian
  • sudo権限なし
  • SSHでログイン可能

 Nitrous.ioの仮想マシンはsudo権限がユーザに付与されていません。仮想マシン作成時に選択した開発言語に応じて、必要なソフトウェアが自動でインストールされます。また、オートパーツというブラウザ上のパッケージマネージャから、追加パッケージをインストールできます。

IDEについて

Codeanywhere
  • 自動でオートコンプリートリストが開く
Nitrous.io
  • ショートカットキー( ctrl + space )でオートコンプリートリストが開く

 Rubyを用いて簡単なチェックを行ったところ、双方ともオートコンプリート機能は備えています。ただし一般的なIDEのように標準関数や別ファイルの関数は補完できません。またリファクタリングなどの強力なサポートはありません。このあたりは双方ともにプロジェクトの概念が無いためかもしれません。

 積極的に人柱になって、プロジェクト概念の導入と、標準関数のオートコンプリートの要望を出していきましょう!

パフォーマンスについて

Codeanywhere
  • 非常に不安定
Nitrous.io

 Codeanywhereは無料版でも有料版でもパフォーマンスは悪く非常に不安定です。それに引き換え、Nitrous.io は非常に安定しています。仮想マシン作成時に設置場所を選択でき、EastAsiaを選択したところ、非常に安定しており、パフォーマンスも良いです。

料金について

Codeanywhere
  • $2から
  • マシンの設置可能台数がプランによって変化
Nitrous.io
  • $7から
  • N2Oというポイントをリソースに割り当てる

 Codeaanywhereは同一スペックのマシンを契約プランに応じた台数分設置できるという料金体系です。Nitrous.ioはN2Oというポイントを利用して仮想マシンを立てたり、仮想マシンのスペックをアップグレードしたり、ユーザが使用方法を自由に選べる料金体系です。

 Codeanywhereは月額$2からスタータープランが用意されているのに対し、Nitrous.ioは月額$7からのスタータープランになっています。同額料金を支払うならCodeanywhereのほうが圧倒的に多くのリソースが手に入ります。

まとめ

「リソースいっぱい使って、いくつも環境作りたい!」という人は料金体系的にCodeanywhereをお勧めしたいところですが、前述したとおり動作が非常に不安定です。日本国内から使用するなら安定性とパフォーマンスの問題から、現時点では Nitrous.io しか選択肢はなさそうです。

nginxモジュールのテストを書く

はじめに

 唐突ですが、仕事でシステムの構成を考えていると、nginxを拡張したいなーとか思うことってあると思います。nginxはC言語で割と簡単に拡張モジュールを書くことができます。(今回は拡張モジュールの書き方については触れませんが・・・)

 だがしかし、仕事なんだからテストコードは必須だよね(迫真)。既存のnginx用のモジュールのコードを眺めてみると、謎の`t`フォルダにテストコードが入っています。
`t`ってなんだよ`t`って!中身もhogehoge.tとかなってるし、t言語なんかあるの? というところから始まり、なんとかテストを書いて実行できるようになったので方法をまとめておきます。

 具体的にはperlのテストフレームワークagentzh/test-nginx · GitHub を利用してテストを書いていきます。

さっきからPerlっていう単語が・・・

 あれって2000年前半にオワコンの技術じゃ・・・と思う人も思いますが、割と進化を続けているようです。(Perlのエロ人、こんな説明ですみません、CGI時代にPerlをちょっと触ったにわかです許して下しあ><)

Perl使ったことないんだけど

 今回紹介するテスト方法はPerlのコードをガリガリ書く必要はないので安心してください。(ここまで簡単にかけるテストフレームワークはむしろ初めてでした。)

テストの準備

必要なもの

 nginxのテストをするために必要なソフトウェアやライブラリです。URLを掲載していないものはUbuntu13.10の公式リポジトリからSynapticを使ってインストールしました。

nginxのコンパイルに必要なもの

 テストを実行する上でecho-nginx-moduleとmemc-nginx-moduleは不可欠でした。
※`/home/develop` 下にecho-nginx-moduleとmemc-nginx-moduleをcloneしていると想定して記事を書いています。

perlでテストを実行するために必要なもの

test-nginxは適当なディレクトリにcloneしておき、テスト実行時にディレクトリを指定します。
※`/home/develop' 下にtest-nginxをcloneしていると想定して記事を書いています。

テストコードの書き方

 nginxモジュールのプロジェクトディレクトリに`t/`というディレクトリを作り、その中に`{任意の名前}.t`という形でテストコードを書いていきます。

use Test::Nginx::Socket;

# テストの実行回数の設定。
repeat_each(3);
plan tests => repeat_each() * 2 * blocks();

# 文字の表示をわかりやすくする。
no_long_string();

# テストの実行
run_tests();

__DATA__

=== TEST 1: ハローワールドのテスト
--- config
    location /hello {
        echo hello_world;
    }
--- request
    GET /hello HTTP/1.0
--- response_body
hello_world
--- error_code: 200

`--- config` にnginxの設定を記述し、`---request` でテストとして実行するリクエストを記述します。
 次に、リクエストに対して`--- response_body` で期待するレスポンスを記述し、 `--- error_code` に期待するレスポンスコードを記述します。

こんなに簡単にかけるテストは見たことはありません!幸せ。

テストの実行

大まかな流れ

 nginxのテストの大まかな流れは次のとおりです。

  1. 自分のモジュールを組み込んだnginxをコンパイル&インストールする。
  2. コンパイルしたnginxのパスを通す。
  3. プロジェクトのディレクトリでproveを実行する。

nginxのコンパイル

 テストを実行するために、自分のモジュールを組み込んだnginxをコンパイルします。私の場合は次のようなオプションでコンパイルしました。

CFLAGS="-O1 -Wall -g" ./configure --add-module=[自分のモジュール] 
   --add-module=/home/develop/echo-nginx-module
   --add-module=/home/develop/memc-nginx-module
   --prefix=/home/develop/nginx --with-debug

特筆すべき点は下記2点です。

  • CFLAGSはvalgrindを利用してプロファイリングを行うことを想定しています。
  • プレフィックスをつけて通常使用するnginxとは分けました。(当然といえば当然ですね。)

proveでテストの実行

 まず、先ほどコンパイルしたnginxにパスを通します。

export PATH=/home/develop/nginx/sbin:$PATH

そしてテストを実行します。

prove -I/home/develop/test-nginx/lib -r t

proveを実行する際にtest-nginxをincludeのがポイントです。

valgrindでプロファイリングする場合

 メモリリークや実行速度についての解析をvalgrindを用いて行う場合にはTEST_NGINX_USE_VALGRINDという環境変数にオプションを記述します。

TEST_NGINX_USE_VALGRIND="{オプション}" prove -I/home/develop/test-nginx/lib -r t

メモリリークのテストをする場合にはこんなかんじでしょうか。

TEST_NGINX_USE_VALGRIND="-v --tool=memcheck --leak-check=full" prove -I/home/develop/test-nginx/lib -r t

RailsのEnumと相性が悪い人向けのInumをバージョンアップさせた話。

はじめに

Railsの列挙型事情

 Rails4.1以前では公式に列挙型が実装されておらず、列挙型を実現するために様々なgemが生み出されてきましたが、Rails4.1でついにActiveRecord::Enumという列挙型のクラスがやっと実装され、長い列挙型宗教戦争が終わろうとしています。

ならオワコンサードパーティの列挙型なんていらないのでは?

 残念ながら妄想していた列挙型ではなかったのです。なのでActiveReocrd::Enumが登場してからもメンテナンスしています。

どうせI18n対応とかじゃないの?

 もちろんI18n対応も理由の一つですが、I18n対応だけで良ければ brainspec/enumerize · GitHub あたりを使うのがベストだと思います。それだけでは足りないほしがりさん向けです。

Inumができること

モデルにロジックを食わせてコレ以上肥満体型にしたくない!

 そんなあなたにInumダイエット。Inumでは列挙型を独立したクラスとして定義するので、モデルに列挙型に関するロジックを書いて太らせるなんてことはありません。(メンテナンス継続理由の大半を占めています。)

class AnimeType < Inum::Base
  define :NYARUKOSAN,   0
  define :NONNONBIYORI, 1
  define :KILLMEBABY,   2

  # セリフを表示する
  def serif
    case self
    when NYARUKOSAN
      "いつもニコニコあなたの隣に這いよる混沌、ニャルラトホテプ、です!"
    when NONNONBIYORI
      "にゃんぱすー"
    when KILLMEBABY
      "キルミーベイベーは復活する、絶対にだ!!"
    end 
  end
end

p AnimeType::KILLMEBABY.serif  # => "キルミーベイベーは復活する、絶対にだ!!"

各位@ActiveRecordとなかよく

 バージョン3.0.0には ActiveRecord support. by alfa-jpn · Pull Request #4 · alfa-jpn/inum · GitHub super friendly ActiveRecord. という内容のプルリクがマージされています。超仲いいです。

class Anime < ActiveRecord::Base
  bind_inum :column=> :anime_type, :class => AnimeType
end

この1行書くだけで、Animeモデルのanime_typeカラム(integer)に列挙型がバインドされ便利なメソッドが定義されます。

anime = Anime.new

# getter/setterで列挙型にラップされます。
anime.anime_type = AnimeType::KILLMEBABY
p anime.anime_type.value # => 2

# 判定用メソッドが追加されます。プレフィックスにカラム名が入りますが、bind_inumのオプションで消せます。
p anime.anime_type_nonnonbiyori? # => false

仲がいいものの依存はしておらず、ActiveRecordは必須ではありません。

I18nで表示名を付けたい

 I18nyamlでinum下に記述することでtranslateできます。

ja:
  inum:
    anime_type:
      nyarukosan:   '這いよれ!ニャル子さん'
      nonnonbiyori: 'のんのんびより'
      killmebaby:   'キルミーベイベー'

 translate メソッドもしくは t メソッドで翻訳できます。

p AnimeType::NONNONBIYORI.t # => "のんのんびより"

パワフルにパーズできる

 わりと何でもパーズしてくれるメソッドが内部にいるので、代入や比較ができます。

# パーサー
p AnimeType.parse(0).t              # => "這いよれ!ニャル子さん"
p AnimeType.parse('NONNONBIYORI').t # => "のんのんびより"
p AnimeType.parse(:KILLMEBABY).t    # => "キルミーベイベー"
p AnimeType.parse(999)              # => nil

# ActiveRecordのsetterでもパーサーが働くのでこんなことや
anime = Anime.new
anime.anime_type = "KILLMEBABY"  

# わりと色々な箇所に仕組んでいるのでこんな風にも使えます。
p (AnimeType::NONNONBIYORI + 1 ).t # => "キルミーベイベー"

EnamerableとComparebleをinclude

 わりと無双な感じ

p AnimeType::KILLMEBABY == 2 # => true
p AnimeType::NONNONBIYORI < AnimeType::KILLMEBABY # => true

AnimeType.each do |enum|
  p enum.t
end

参考サイト

Rails4と3で論理削除を行うためのGem Kakurenbo の紹介と今更論理削除Gemを実装した理由。

様々なわけがあってkakurenboは非推奨です。新規のプロジェクトではkakurenbo-putiの使用をおすすめします。

Kakurenboとは

 Rails4及びRails3で論理削除を行うためのGemです。paranoia及びacts_as_paranoidと互換性があるので、gemを置き換えるだけでそのまま動きます。(動かなかったらissue投げてくだしあ><)

なんで今更論理削除のGemを実装したのか

 今更開発しなくても論理削除のGemは山ほど出てきますが、なぜ開発しなくてはならなくなってしまったのか経緯に触れておきます。

acts_as_paranoid

 論理削除の本家と言ってもいいレベルの知名度です、だがしかしいつまで立ってもRails4に対応しない。

rails4_acts_as_paranoid

 既存のバグほったらかしで使えない。(メモリ関連のバグがありSQLクエリが永遠に結合されていきます。やばみ。プルリク送ったのに放置されてます。)

paranoia

 今Rails4で論理削除と言ったらコレ!ってくらい定番です。私もつい最近まではコレを利用していました。コールバック関連のバグを修正するプルリク送ったりして結構便利に使っていました。
 しかし、とある作業中にアソシエーションに深刻な問題があることに気付き、プルリクを送りましたが、仕様なのでマージする気はないとプルリク蹴られてしまいました。

 具体的にはリレーショナルで1対多の関係を設定している場合、親を論理削除して復元を行った場合、親が論理削除される以前に論理削除されている子まで復元されてしまうのです。例えば掲示板で、掲示板を本体を論理削除した後、何かの手違いだとわかり復元する時に、問題があって削除してた書き込みも全て復元されてしまうのです。

 「そもそも間違えて削除しなければいい話だろ」なんて運用でカバーするスタイルはRailsRubyらしくありません。だからこれは深刻な問題です。大切なことなのでもう一度言います。これは深刻な問題です。

結論

 paranoiaをフォークして作ろうと思ったものの、paranoiaのテストフォルダにはTest::Unitで書かれた、生SQLクエリでテーブル生成したり、実行順番依存で書かれた闇のテストコードが・・・ → Rspecで綺麗にテスト書きながら最初から作ろう。

 かくして、新しくKakurenbo*1を開発することになるのであった。。。。

インストール方法

 いつものようにGemfileに追加するとか、インストールするとか。

gem "kakurenbo"

使い方

 論理削除で管理したいモデルに deleted_at カラムを datetime 型で追加するだけで使えます。

rails generate migration add_deleted_at_to_models deleted_at:datetime

クラスの初期化時にカラムを読み取って、deleted_atがあれば論理削除と判別するので論理削除のモデルでいちいちacts_as_paranoidメソッドを呼び出す必要はありません。
(deleted_at以外のカラムを利用する際には、acts_as_paranoidをcolumnオプション付きで呼び出して設定してください。)

基本的な使い方

 paranoiaやacts_as_paranoidと互換性があるので説明はいらないかもしれませんが基本的な使い方です。

この記事は古くなっています、最新バージョン 0.2.x の使い方はこちらを参照してください。

論理削除Gem、 Kakurenbo をアップデートしました。 - 波打際のブログさん

論理削除

 普通にdestroyメソッドを呼び出すと論理削除されます。

model.destroy
復元

 論理削除したモデルはrestoreで復活できます。

model.restore!

# 次の方法も使えます。id指定、もしくはidの配列で一括で復元できます。
Model.restore(id)

before_restore, after_restoreコールバック使えます。

物理削除

 destroy!で物理削除できます。

model.destroy!
スコープ
# 削除されたモデルも取得
Model.with_deleted

# 削除されたモデルのみ取得
Model.only_deleted

# 削除されていないモデルのみ取得(デフォルトスコープです。)
Model.without_deleted

関連リンク

修正履歴

  • 2014年01月29日 誤字脱字を修正しました。

*1:RailsとかRubyのGemって、流行ってるのってみんな変な名前だよね!じゃぁ俺も変な名前のGem作ろう・・・論理削除・・・かくれみの・・・かくれんぼ!! → Kakurenbo

Ubuntu13.10でiBusを捨ててfcitxを使う

はじめに

 Ubuntu13.10がリリースされて3ヶ月ほど立ちました。Ubuntuのサポート期間はLTS版を除き、9ヶ月というとても短い設定となっています。今まで使用してたUbuntu13.04のサポート期限は去年の12月いっぱいなので、継続して使用するためにUbuntuのバージョンを13.10にアップグレードしたところ、インプットメソッドiBusが1.5にアップグレードされ、非常に使いにくいものとなっていました。
 はじめのうちはiBusと仲良くなる努力はしましたが不可能であることを悟り、今話題のfcitxを利用することにしました。これは導入に関するまとめです。

fcitxの良い所

  • iBus1.4と同様の感覚で日本語入力ができる。
  • iBusよりもカスタマイズできる箇所が多い。(候補ウィンドウの配色やフォント、テーマなど)
  • Mozcのユーティリティへのアクセスがしやすい。(設定ツールや辞書ツールをワンクリックで呼び出せる)

fcitxの悪い所

  • 半角/全角キーを長めに押さないとIMが切り替わらない事がある。(もしかしたら設定の問題?)

導入

パッケージのインストール

 Ubuntuソフトウェアセンターか、apt-getでfcitx-mozcをインストールすると、依存関係が設定されているので必要なものがすべて芋づる式でインストールされます。
f:id:alfa-jpn:20140113140804p:plain

デフォルトでfcitxを使用する設定にする

 パッケージのインストールが完了したら システム設定の言語サポートから、「キーボード入力に使うIMシステム」の設定をfcitxに設定します。設定が完了したらコンピュータを再起動させます。
f:id:alfa-jpn:20140113141130p:plain

iBusのインジケータを非表示にする

 再起動するとfcitxのインジケータと、iBusのインジケータが表示されていると思うので、システム設定のテキスト入力から、「メニューバーに現在の入力ソースを表示」のチェックボックスを外し、iBusのインジケータ表示を無効にします。
f:id:alfa-jpn:20140113141609p:plain

fcitxの設定

 この設定が完了すると、fcitxは既に使用できる状態になってますが、デフォルトでは半角/全角に割り当てられているキーマップが、mozcの半角全角と競合してしまっているために、おかしな挙動になってしまいます。そこで、mozcに割り当てられている半角/全角キーのキーマップを全て削除します。

 メニューバーのfcitxのアイコンをクリックし、Mozcツール(表示されていない場合はテキスト入力画面で半角/全角キーを押して、IMをMozcに切り替えてください)から設定ツールをクリックします。Mozc設定ツールが起動したら、一般タブの中のキー設定項目右側にある編集ボタンをクリックするとキー設定ウィンドウが表示されます。

 キー設定ウィンドウの上部にある入力キーのタブをクリックし、入力キーの名前順にリストを並び替え、Hankaku/Zenkakuの設定4つ全てを削除します。
f:id:alfa-jpn:20140113142200p:plain

以上で設定は完了です、設定が完了したら念の為に再起動を行います。