RailsとDeviseで管理者ユーザーを作ることに成功した

昼過ぎから半日いろいろとやって、やっと成功したので忘れないうちに手順をメモ。

users テーブルに admin 列を作る

まずは管理者マークをつけるために users テーブルに admin 列を作る。この列が true のユーザーが管理者(admin)てわけ。いろいろググってみると専用のテーブルを作っている例もあるけど、ここはお手軽な方法でいくことにした。

takatoh@nightschool $ rails generate migration add_admin_to_useres admin:boolean

できたマイグレーションファイルを編集。null: falsedefault: false を追記。

class AddAdminToUsers < ActiveRecord::Migration
  def change
    add_column :users, :admin, :boolean, null: false, default: false
  end
end

でもってマイグレーション実行。

takatoh@nightschool $ rake db:migrate

config/initializers/devise.rbを編集

次の行がコメントアウトされているのをやめて、false を true に変更。

config.scoped_views = true

Deviseのviewをコピーして編集

takatoh@nightschool $ rails generate devise:views users

上のコマンドで Devise の標準の view がアプリの中にコピーされる。できたファイルのうち、サインアップに使う app/views/users/registrations/new.html.erb を編集して admin 用のチェックボックスを追加。

<h2>Sign up</h2>
  <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  <div>
    <%= f.label :email %>
    <%= f.email_field :email, autofocus: true %>
  </div>
  <div>
    <%= f.label :password %>
    <%= f.password_field :password, autocomplete: "off" %>
  </div>
  <div>
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>
  <% if @noadmin %>
  <div>
    <%= f.label :admin %>
    <%= f.check_box :admin, { }, true, false %>
  </div>
  <% end %>
  <div>
    <%= f.submit "Sign up" %>
  </div>
  <% end %>

<%= render "users/shared/links" %>

controllerの修正

最後は controller の修正。2つ修正がある。ひとつは app/controllers/application_controller.rb。

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_filter :configure_permitted_parameters, if: :devise_controller?

  private

  def after_sign_in_path_for(resource)
    "/dashboard/"
  end

  def check_signed_in
    unless signed_in?
     redirect_to '/'
    end
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :admin
    devise_parameter_sanitizer.for(:account_update) << :admin
  end
end

もうひとつは app/controllers/users/regitrations_controller.rb。

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    @user = User.new
    @noadmin = User.where('admin = ?', true).empty?
  end
end 

これで終了。

確認

1st-user-sign-up

初めてのユーザーがサインアップしようとしているところ。Admin のチェックボックスが表示されている。ここをチェックしてサインアップすれば管理者になる。

2nd-user-sign-up

で、これが2人目のユーザーがサインアップしようとしているところ。Adminのチェックボックスは表示されていない。

参考にしたページ

 cf. 【Rails4】deviseとactive_adminで一般ユーザーと管理者ユーザーを作成 – avosalmonのブログ
 cf. Rails の認証プラグイン Devise での Strong Parameters について – EasyRamble
 cf. DeviseでViewをカスタマイズする – Qiita

Ubuntuの端末のプロンプトをカスタマイズ

デフォルトでは「ユーザー名@ホスト名:カレントディレクトリ$」となってるんだけど、長いので短くしたい。特にディレクトリの深いところまで行くと1行じゃ納まらなくなったりしてすごく邪魔。
というわけで、↓このページを参考に変更してみた。

 cf. Ubuntu 端末のコマンドプロンプトをカスタマイズしてユーザー名やコンピューター名を非表示にする – Ubuntuアプリのいいところ

リンク先のページでは、ユーザー名とホスト名を消してるけど、上にも書いたとおりディレクトリを消したほうがシンプルになる。
具体的には、.bashrc を PS1 変数を設定している部分(俺の環境では60行目付近)を編集する。

takatoh@nightschool:~$ subl .bashrc
else
    # PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
    PS1='${debian_chroot:+($debian_chroot)}\u@\h \$ '
fi

コメントアウトしてあるのが元の行。\w がカレントディレクトリを指しているみたいだ。
で、これを適用するとこうなった。

takatoh@nightschool:~$ source .bashrc
takatoh@nightschool $ 

Node.jsでファイルをダウンロードする(2)

今日はちょっと進んで、JSON 形式のファイルから URL のリストを読み込んでダウンロードする。

var http = require('http');
var fs = require('fs');
var path = require('path');

var list = process.argv[2];

var urls = JSON.parse(fs.readFileSync(list, 'utf8'));
urls.forEach(function(url) {
  console.log(url);
  var filename = path.basename(url);

  // output stream
  var outFile = fs.createWriteStream(filename);

  var req = http.get(url, function(res) {
    res.pipe(outFile);
    res.on('end', function() {
      outFile.close();
    });
  });

  // error handler
  req.on('error', function(err) {
    console.log('Error: ' + err.message);
    return;
  });
});

Node.jsでファイルをダウンロードする

↓このページを参考に書いてみた。っていうかほとんどそのまんまだけど。

 cf. [NodeJS] ファイルをダウンロードする – YoheiM.NET

var http = require('http');
var fs = require('fs');
var path = require('path');

var url = process.argv[2];
console.log(url);
var filename = path.basename(url);

// output stream
var outFile = fs.createWriteStream(filename);

var req = http.get(url, function(res) {
  res.pipe(outFile);
  res.on('end', function() {
    outFile.close();
  });
});

// error handler
req.on('error', function(err) {
  console.log('Error: ' + err.message);
  return;
});

変えたのは URL から保存するファイル名を決めるとことだけ。

このスクリプトのキモは、res.pipe でデータをアウトプットストリームに流しこんでいるところ。で、end イベントが発生したらストリームを閉じる、と。

deviseでユーザー名とパスワードでの認証がうまくいかなかった件

まずは今朝の最後に貼った画面を再掲する。

sign-in-with-name-and-email

見ての通り、サインアップするのにユーザー名、メールアドレス、パスワードの3つが必要だ。これでは面倒なので、ユーザー名とパスワードだけでサインインできるようにしたいと思った。

で、グーグルさんでいろいろ調べてみるとわりと簡単そうだったんだけど、結果から言うとうかくいかなかった。なんでだかわからない。
config/initializers/devise.rb の編集もしたし、ApplicationController に before_filter (configure_permitted_parameters)も書いてみた。けどうまくいかなかった。なんか色々やってるうちにわからなくなってしまった。
さらに、サインアップのときに登録したはずのユーザー名がデータベースに保存されていないことが発覚。ということはつまり、今朝の時点でもうまくいっていなかったってことだ。

結局、メールアドレスとパスワードで認証するところまで巻き戻して、devise をこれ以上いじるのはやめにして、他を進めることにした。devise は、また何か新しい情報を見つけたら試してみよう。

deviseをカスタマイズする

Rails と devise の話はまだ続くよ。今日は devise のビューとコントローラをカスタマイズする。

やっぱりユーザー名がほしい

ユーザーアカウントに Email だけじゃなくて、やっぱりユーザー名がほしい。というわけで、migration スクリプトに2行追加。

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :name, null: false, default: ""
      t.string :email, null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string :current_sign_in_ip
      t.string :last_sign_in_ip

      ## Confirmable
      t.string :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string :unconfirmed_email      # Only if using reconfirmable

      ## Lockable
      # t.integer :failed_attempts, default: 0, null: false
      # Only if lock strategy is :failed_attempts
      # t.string :unlock_token
      # Only if unlock strategy is :email or :both
      # t.datetime :locked_at t.timestamps
    end

    add_index :users, :name, unique: true
    add_index :users, :email, unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token, unique: true
    # add_index :users, :unlock_token, unique: true
  end
end

そしてデータベースの作り直し。

takatoh@nightschool:~/w/lathercraft$ bundle exec rake db:drop
takatoh@nightschool:~/w/lathercraft$ bundle exec rake db:migrate

devise のビューをコピーしてカスタマイズ

デフォルトでは gem のビューが使われているけど、カスタマイズするためにビューをコピーする。

takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise:views users
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/users/shared
      create    app/views/users/shared/_links.erb
      invoke  form_for
      create    app/views/users/confirmations
      create    app/views/users/confirmations/new.html.erb
      create    app/views/users/passwords
      create    app/views/users/passwords/edit.html.erb
      create    app/views/users/passwords/new.html.erb
      create    app/views/users/registrations
      create    app/views/users/registrations/edit.html.erb
      create    app/views/users/registrations/new.html.erb
      create    app/views/users/sessions
      create    app/views/users/sessions/new.html.erb
      create    app/views/users/unlocks
      create    app/views/users/unlocks/new.html.erb
      invoke  erb
      create    app/views/users/mailer
      create    app/views/users/mailer/confirmation_instructions.html.erb
      create    app/views/users/mailer/reset_password_instructions.html.erb
      create    app/views/users/mailer/unlock_instructions.html.erb

とりあえず、sign up するときの app/views/users/registrations.new.html.erb と sign in するときの app/views/users/sessions/new.html.erb にユーザー名の欄を付け加えた。

<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  <div>
    <%= f.label :name %>
    <%= f.email_field :name, autofocus: true %>
  </div>
  <div>
    <%= f.label :email %>
    <%= f.email_field :email %>
  </div>
  <div>
    <%= f.label :password %>
    <%= f.password_field :password, autocomplete: "off" %>
  </div>
  <div>
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>
  <div>
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "users/shared/links" %>
<h2>Sign in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div>
    <%= f.label :name %>
    <%= f.email_field :name, autofocus: true %>
  </div>
  <div>
    <%= f.label :email %>
    <%= f.email_field :email %>
  </div>
  <div>
    <%= f.label :password %>
    <%= f.password_field :password, autocomplete: "off" %>
  </div>
  <% if devise_mapping.rememberable? -%>
  <div>
    <%= f.check_box :remember_me %>
    <%= f.label :remember_me %>
  </div>
  <% end -%>
  <div>
    <%= f.submit "Sign in" %>
  </div>
<% end %>

<%= render "users/shared/links" %>

コントローラーのカスタマイズ

コントローラーをカスタマイズするには、Devise::SessionsController, Devise::RegistrationsController, Devise::PasswordsController を継承したクラスを作成して、各メソッドをオーバーライドすればいいようだ。どのメソッドをオーバーライドすればいいかを、bundle exec rake routes で確認する。

takatoh@nightschool:~/w/lathercraft$ bundle exec rake routes
                  Prefix Verb   URI Pattern                       Controller#Action
        new_user_session GET    /users/sign_in(.:format)          devise/sessions#new
            user_session POST   /users/sign_in(.:format)          devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)         devise/sessions#destroy
           user_password POST   /users/password(.:format)         devise/passwords#create
       new_user_password GET    /users/password/new(.:format)     devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)    devise/passwords#edit
                         PATCH  /users/password(.:format)         devise/passwords#update
                         PUT    /users/password(.:format)         devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)           devise/registrations#cancel
       user_registration POST   /users(.:format)                  devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)          devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)             devise/registrations#edit
                         PATCH  /users(.:format)                  devise/registrations#update
                         PUT    /users(.:format)                  devise/registrations#update
                         DELETE /users(.:format)                  devise/registrations#destroy
       user_confirmation POST   /users/confirmation(.:format)     devise/confirmations#create
   new_user_confirmation GET    /users/confirmation/new(.:format) devise/confirmations#new
                         GET    /users/confirmation(.:format)     devise/confirmations#show
(後略)

これを見ると、とりあえずは registration#new と sessions#new かな。それぞれこうした。

class Users::RegistrationsController < Devise::RegistrationsController
end
Devise::SessionsController
  def new
    super
  end

  def create
    super
  end

  def destroy
    super
  end
end

ついでに PasswordsController も。

class Users::PasswordsController < Devise::PasswordsController
end

ルーティングの設定

作ったコントローラーを使うように、ルーティングを変更する。

Rails.application.routes.draw do
  devise_for :users, :controllers => {
    :registrations => "users/registrations",
    :sessions      => "users/sessions",
    :passwords     => "users/passwords"
  }
(後略)

ルーティングを確認してみよう。

takatoh@nightschool:~/w/lathercraft$ bundle exec rake routes
                  Prefix Verb   URI Pattern                       Controller#Action
        new_user_session GET    /users/sign_in(.:format)          users/sessions#new
            user_session POST   /users/sign_in(.:format)          users/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)         users/sessions#destroy
           user_password POST   /users/password(.:format)         users/passwords#create
       new_user_password GET    /users/password/new(.:format)     users/passwords#new
      edit_user_password GET    /users/password/edit(.:format)    users/passwords#edit
                         PATCH  /users/password(.:format)         users/passwords#update
                         PUT    /users/password(.:format)         users/passwords#update
cancel_user_registration GET    /users/cancel(.:format)           users/registrations#cancel
       user_registration POST   /users(.:format)                  users/registrations#create
   new_user_registration GET    /users/sign_up(.:format)          users/registrations#new
  edit_user_registration GET    /users/edit(.:format)             users/registrations#edit
                         PATCH  /users(.:format)                  users/registrations#update
                         PUT    /users(.:format)                  users/registrations#update
                         DELETE /users(.:format)                  users/registrations#destroy
       user_confirmation POST   /users/confirmation(.:format)     devise/confirmations#create
   new_user_confirmation GET    /users/confirmation/new(.:format) devise/confirmations#new
                         GET    /users/confirmation(.:format)     devise/confirmations#show
(後略)

confirmation のルーティングが devise のままだけど大丈夫かな。

試しにサインアップしてみると、無事うまく行った。

sign-in-with-name-and-email

deviseでサインアップした時にメールを送れるようにする

引き続き devise の話。confirmation 用のメールを送る設定。
config/environments/development.rb に次の設定を追加する。

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :address        => 'smtp.gmail.com',
  :port           => 587,
  :authentication => :plain,
  :user_name      => 'メールアドレス',
  :password       => 'パスワード'
}

とはいえ、メールアドレスやパスワードをハードコーディングするのは良くないよなあ。どうやるのがいいんだろ。

追記

メールアドレスやパスワードの設定場所は、以下のページによると config フォルダ以下に .yml ファイルを作って、config/initializers フォルダにおいたスクリプトで読み込むのがいいらしい。

 cf. Railsの設定情報 – Build INSIDER
 cf. Rails でアプリ固有の設定情報や定数を定義する – EasyRamble

そこで、次のように config/app_config.yaml と config/initializers/app_config.rb を作った。

---
development:
  email: メールアドレス
  email_password: パスワード
test:
  email: メールアドレス
  email_password: パスワード
production:
  email: メールアドレス
  email_password: パスワード
APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]

ところが、これで Rails コンソールを立ち上げようとするとエラーになる。

takatoh@nightschool:~/w/lathercraft$ rails console
/home/takatoh/w/lathercraft/config/environments/development.rb:44:in block in ': uninitialized constant APP_CONFIG (NameError)
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/railtie.rb:210:in instance_eval'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/railtie.rb:210:in configure'
	from /home/takatoh/w/lathercraft/config/environments/development.rb:1:in '
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/engine.rb:594:in block (2 levels) in '
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/engine.rb:593:in each'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/engine.rb:593:in block in '
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:30:in instance_exec'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:30:in run'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:55:in block in run_initializers'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:226:in block in tsort_each'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:348:in block (2 levels) in each_strongly_connected_component'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:418:in block (2 levels) in each_strongly_connected_component_from'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:427:in each_strongly_connected_component_from'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:417:in block in each_strongly_connected_component_from'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:44:in each'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:44:in tsort_each_child'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:411:in call'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:411:in each_strongly_connected_component_from'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:347:in block in each_strongly_connected_component'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:345:in each'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:345:in call'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:345:in each_strongly_connected_component'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:224:in tsort_each'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/tsort.rb:205:in tsort_each'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/initializable.rb:54:in run_initializers'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/application.rb:300:in initialize!'
	from /home/takatoh/w/lathercraft/config/environment.rb:5:in '
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application.rb:92:in preload'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application.rb:140:in serve'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application.rb:128:in block in run'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application.rb:122:in loop'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application.rb:122:in run'
	from /home/takatoh/.rvm/gems/ruby-2.1.1/gems/spring-1.1.3/lib/spring/application/boot.rb:18:in '
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in require'
	from /home/takatoh/.rvm/rubies/ruby-2.1.1/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in require'
	from -e:1:in main'

最初の方に書いてあるけど、APP_CONFIG 定数が初期化されていない、と出てる。推測するに、config/initializers/app_config.rb よりも config/environments/development.rb (ここで APP_CONFIG を参照している)のほうが先に読み込まれるんではなかろうか。
結局、他に方法が思いつかなかったので、config/app_config.yml を config/envronments/development.rb の中で読み込むように変更した。

APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]

config.action_mailer.default_url_options = { :host =&gt; 'localhost:3000' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :address        => 'smtp.gmail.com',
  :port           => 587,
  :authentication => :plain,
  :user_name      => APP_CONFIG["email"],
  :password       => APP_CONFIG["email_password"]
}

これでうまく動いた。

deviseでsign in/sign up/sign outへのリンク

昨日に続いて、devise の話。sign in/sign up/sign out それぞれへのリンクをつけた。こんな感じ。

<ul>
  <li style="list-style-type: none;">
    <ul>
<% if user_signed_in? %>
    </ul>
  </li>
</ul>
<ul>
  <li style="list-style-type: none;">
    <ul>
      <li><%= link_to "Sign out", destroy_user_session_path, :method => :delete %></li>
    </ul>
  </li>
</ul>
<% else %>
      <ul>
        <li style="list-style-type: none;">
      <ul>
      <li><%= link_to "Sign in", new_user_session_path %></li>
      <li><%= link_to "Sign up", new_user_registration_path %></li>
    </ul>
  </li>
</ul>
<% end %>

サインインしているときは、Sign out だけ、していないときは Sign in と Sign up へのリンクを表示する。

Railsアプリにdeviseでユーザー認証を

先日から作り始めた Web アプリに、ユーザー認証を付けたい。ググってみると、devise っていうのがいいみたいなので、それを使うことにした。参考にしたのは以下のページ。

 cf. Railsでログイン、ユーザー登録機能を簡単に実装できる devise がスゴすぎると話題 – lough-raku^^
 cf. Rails4 にて Devise でユーザー登録・ログイン認証・認可の機能を追加 – EasyRamble
 cf. DeviseでSign up時にメール確認する – 悪あがきプログラマー

まずはインストール

Gemfile に以下の行を追加。

gem 'devise'

そいでもってインストール。

takatoh@nightschool:~/w/lathercraft$ bundle install

ジェネレータでモデルを作成

takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise:install
takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise User

モデル名は User にした。この時点で次のようなマイグレーションファイルができる。今回はユーザー名を入れたかったので name フィールドを追加、加えて Email での確認をしたかったので、confirmable のところがコメントアウトしてあったのを外した。

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :name, null: false, default: ""
      t.string :email, null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable t.integer :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string :current_sign_in_ip
      t.string :last_sign_in_ip

      ## Confirmable
      t.string :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string :unconfirmed_email     # Only if using reconfirmable

      ## Lockable
      # t.integer :failed_attempts, default: 0, null: false
      # Only if lock strategy is :failed_attempts
      # t.string :unlock_token
      # Only if unlock strategy is :email or :both
      # t.datetime :locked_at
      t.timestamps
    end

    add_index :users, :email, unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token, unique: true
    # add_index :users, :unlock_token, unique: true
  end
end

これで rake db:migration、サーバを起動して localhost:3000/users/sign_up にアクセスすると、下の画面のようにサインアップできるようになる。

user-sign-up

Sign up ボタンをクリックすれば OK だ。といってもまだメールを送る設定とかしていないので、サインアップは完了できない。でも、ログには出てくるはず……って、あれぇ?エラーになった。

devise-registration-error

なんでだ?
参考にしたページによれば、ログにメールが出力されて confirm 用のページへのリンクが乗っているはずなんだけど。うーん、勝手に name カラムを追加したのが悪いんだろうか。

いろいろ調べて試した結果

↓このページで答えを見つけた。

 cf. Ruby on Rails + Deviseの組み合わせでMissing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true – もっとクールにプログラミング

それと他にも間違いと思しきところが。結局直したのは次の3ヶ所。

1つ目は、マイグレーションファイルの下の方で次の行がコメントアウトされていたのを有効にした。

add_index :users, :confirmation_token, unique: true

2つ目は、app/models/user.rb に :confirmable オプションを追加した。

最後、3つ目が上のページにも書いてあるように、config/environments/development.rb の最後に一行追加。

config.action_mailer.default_url_options = { :host =&gt; 'localhost:3000' }

これでやっと、メールがログに出るようになった。

confirmation

href=”…” に示されているアドレスにアクセスすると、無事サインインの画面が出てサインインできた。

めでたしめでたし。というところで、今日はここまで。

Ubuntuの/home/takatohディレクトリをDeja DupでAmazon S3にバックアップする→失敗?

Deja Dup はファイル/ディレクトリのバックアップアプリ(本来は e と a の上に記号がつくんだけど入力できないので省略する)。Ubuntu の画面の左上のボタンを押して、Deja Dup で検索すると「バックアップ」ていうアプリが見つかる。これがどうも Deja Dup …なのか?
でもこのままだとバックアップ先の候補に Amazon S3 が出てこないので、Ubuntu ソフトウェアセンターで deja dup で検索して、Amazon S3 support
for Deja Dup をインストールする。そうすると S3 をバックアップ先に選べるようになる。

改めて「バックアップ」を立ち上げよう。バックアップするフォルダー(ホーム(takatoh))と無視するフォルダー(ゴミ箱と ~/Downloads)はデフォルトのまま。保存場所に Amazon S3 を選ぶと、S3 Access Key ID とフォルダーを入力するように画面が変化する。Access Key ID は AWS で取得したやつだとして、フォルダーの指定の仕方がよくわからないな。とりあえず、バケット名/フォルダ名(panicblanket/backup/nightschool)としてみた。スケジュールはどういうわけか保存期間しか入力できない。これもデフォルトのまま「期限なし」(ほかに「最低6か月」と「最低1年」が選べる)。
さて、これで「概要」の戻って「今すぐバックアップ」をクリックする。すると今度は「Amazon S3に接続」というタイトルで、Secret access key を入力する画面になった。キーを入力して「続行する」をクリック。結果、「バックアップに失敗しました」となった。なんでだ。

ググっても有用な情報は出てこない。そうこうするうち、うっかり自動バックアップを有効にしてしまったら、もう一度無効にしても「今すぐバックアップ」ボタンがグレイアウトしてしまった。こうなったら「次回のバックアップは今日です。」と書いてあるのを信じるしかない……んだけど、そもそも設定があってるのかわからないからなぁ……