jugyo

  • mocktra を使って sinatra で webmock しよう

    mocktra というものを作りました。 これを使うと sinatra の DSL で web の stub が書けます。 内部で webmock というライブラリを使っています。 webmock をできるだけ直感的に使いたかったのでこれを作りました。 例えば Rails アプリなんかで外部の Web サービスの API を呼び出すような処理があるときに、 開発環境ではその部分を stub で置き換えるといった用途で便利に使えるはずです。 下のサンプルコードを見ていただけると何を言ってるのかわかると思います。

    インストール

    $ gem install mocktra
    

    使い方

    Mocktra(url) do ... end のブロックの中に sinatra の DSL で stub としての動作を記述していきます。

    require 'mocktra'
    
    Mocktra('www.example.com') do
      get '/foo' do
        'FOO!!'
      end
    end
    

    irb 等で、上記の処理を実行した後、以下のようにして stub の動作を確認してみましょう。

    require 'net/http'
    puts Net::HTTP.get('www.example.com', '/foo')
    

    FOO!! という文字列が出力されれば成功っす。

  • simple_form の使い方(書きかけ)

    概要

    SimpleForm aims to be as flexible as possible while helping you with powerful components to create your forms. The basic goal of simple form is to not touch your way of defining the layout, letting you find the better design for your eyes. Most of the DSL was inherited from Formtastic, which we are thankful for and should make you feel right at home.

    インストール

    Gemfile に以下を記述し、

    gem 'simple_form'
    

    以下を実行

    $ bundle
    

    さらに以下を実行

    $ rails generate simple_form:install
    

    設定

    後で書く

    使い方

    基本

    <%= simple_form_for @user do |f| %>
      <%= f.input :username %>
      <%= f.input :password %>
      <%= f.button :submit %>
    <% end %>
    

    label や hint、 placeholder を上書きできる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username, :label => 'Your username please' %>
      <%= f.input :password, :hint => 'No special characters.' %>
      <%= f.input :email, :placeholder => 'user@domain.com' %>
      <%= f.button :submit %>
    <% end %>
    

    label や hint、 error を無効にすることもできる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username, :label_html => { :class => 'my_class' } %>
      <%= f.input :password, :hint => false, :error_html => { :id => 'password_error'} %>
      <%= f.input :password_confirmation, :label => false %>
      <%= f.button :submit %>
    <% end %>
    

    どんな html 要素も :input_html によって付け加えることができる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username, :input_html => { :class => 'special' } %>
      <%= f.input :password, :input_html => { :maxlength => 20 } %>
      <%= f.input :remember_me, :input_html => { :value => '1' } %>
      <%= f.button :submit %>
    <% end %>
    

    すべての input 要素に同じオプション(例: デフォルトの class)を渡したい場合は、 :defaults オプションが simpleformfor に対して使える。

    <%= simple_form_for @user, :defaults => { :input_html => { :class => 'default_class' } } do |f| %>
      <%= f.input :username, :input_html => { :class => 'special' } %>
      <%= f.input :password, :input_html => { :maxlength => 20 } %>
      <%= f.input :remember_me, :input_html => { :value => '1' } %>
      <%= f.button :submit %>
    <% end %>
    

    SimpleForm は label と input の周りにラッパーとなる div を生成するんだけど、 :wrapper_html というオプションを使ってそれに html 属性を付け加えることができる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username, :wrapper_html => { :class => 'username' } %>
      <%= f.input :password, :wrapper_html => { :id => 'password' } %>
      <%= f.input :remember_me, :wrapper_html => { :class => 'options' } %>
      <%= f.button :submit %>
    <% end %>
    

    デフォルトではすべての input は必須項目となっていて、 それは * が label に付くことを意味するが、 どの input でもそれを無効にすることができる

    <%= simple_form_for @user do |f| %>
      <%= f.input :name, :required => false %>
      <%= f.input :username %>
      <%= f.input :password %>
      <%= f.button :submit %>
    <% end %>
    

    デフォルトの input タイプを上書きすることができる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username %>
      <%= f.input :password %>
      <%= f.input :description, :as => :text %>
      <%= f.input :accepts,     :as => :radio_buttons %>
      <%= f.button :submit %>
    <% end %>
    

    :disabled オプションを使って input 要素を無効にすることができる

    <%= simple_form_for @user do |f| %>
      <%= f.input :username, :disabled => true, :hint => 'You cannot change your username.' %>
      <%= f.button :submit %>
    <% end %>
    

    SimpleForm は Rails のヘルパーと一致するオプションを受け付ける

    <%= simple_form_for @user do |f| %>
      <%= f.input :date_of_birth, :as => :date, :start_year => Date.today.year - 90,
                                  :end_year => Date.today.year - 12, :discard_day => true,
                                  :order => [:month, :year] %>
      <%= f.button :submit %>
    <% end %>
    

    label, hint, inputfield, error, fullerror といったヘルパーを直接使うこともできる

    <%= simple_form_for @user do |f| %>
      <%= f.label :username %>
      <%= f.input_field :username %>
      <%= f.hint 'No special characters, please!' %>
      <%= f.error :username, :id => 'user_name_error' %>
      <%= f.full_error :token %>
      <%= f.submit 'Save' %>
    <% end %>
    

    (他にもトピックいっぱい)

    Collections

    Priority

    Wrapper

    アソシエーション

    ボタン

    Rails のフォームヘルパーをラップする

    特別なヘルパー

    マッピング

    カスタム input

    カスタムフォームビルダー

    i18n

    HTML 5 Notice

  • enumerize 便利♡ - Enumerated attributes with I18n and ActiveRecord/Mongoid support

    経緯

    Rails で使えるこういうライブラリを探してた

    • モデルのカラムの型を enum 的にしたい(例: role => [:user, :admin])
    • それをもとにセレクトボックスとか簡単に作りたい
    • i18n 対応しててほしい
    • DB には数値ではなく文字列として値そのものが入るようであってほしい

    で、 enumerize というのを見つけた。

    https://github.com/twinslash/enumerize

    使ってみて、これこそ僕が求めていたものだ!という結論に至った。

    では使い方を見ていこう♪

    セットアップ

    Gemfile に以下を追記し、

    gem 'enumerize'
    

    以下を実行

    $ bundle
    

    おきまりやね☆

    使い方

    通常 ActiveRecord のモデルで使うだろうから ActiveRecord のケースだけ書くけど、普通のクラスとか Mongoid でも使えるっぽいよ。

    ActiveRecord 編

    class User < ActiveRecord::Base
      include Enumerize
      enumerize :sex, :in => [:male, :female]
      enumerize :role, :in => [:user, :admin], :default => :user
    end
    

    README の例からパクってきただけなんだけど、もうこれでだいたい使い方わかるよね。

    i18n

    User モデルの sex という enum のそれに対する i18n のあれはこんな感じ

    en:
      enumerize:
        user:
          sex:
            male: "Male"
            female: "Female"
    

    sex という enum のそれを他のモデルでも使ったりするんであれば user という階層を抜かしてこんなふうにも書いてしまえるみたい

    en:
      enumerize:
        sex:
          male: "Male"
          female: "Female"
    

    i18n のテキストを得るには以下のようにする

    @user.sex_text
    

    こうでもいける(僕はこっちのほうが好みかな)

    @user.sex.text
    

    フォームでこんなふうにしてセレクトボックスを作れる(便利ー♪)

    <%= form_for @user do |f| %>
      <%= f.select :sex, User.sex.options %>
    <% end %>
    

    あと、真偽値を返す便利メソッドも用意してくれる(ありがたい)

    user.sex = :male
    user.sex.male? #=> true
    user.sex.female? #=> false
    

    ノート

    • 非常にシンプルで便利で必要最低限のいいやつって感じ
    • いまのところ特に不満はない
    • 最近公開されたライブラリっぽいんだけど、どうして今までこういう感じのなかったんだろ(他に似たようなのいろいろあって調べたけどどれも何か変だった)
  • Rails で RSpec のセットアップ

    朝のプチ勉強会、今日は RSpec についてやりました。Rails で RSpec のセットアップを行い、簡単なサンプルを動かしました。

    Rails アプリケーションの作成

    $ rails new my-app -T
    

    Gemfile に以下を追記して bundle install

    gem 'rspec-rails'
    

    rspec:install

    rspec:install を実行

    $ rails g rspec:install
    

    すると以下のファイルが作成される

        create  .rspec
        create  spec
        create  spec/spec_helper.rb
    

    .rspec

    .rspec には rspec コマンドの引数を記述できる。以下のように設定すると実行結果が見やすくなって良い。

    --color -f d
    

    spec/spec_helper.rb

    spec/spec_helper.rb には設定等を記述する。各 spec でこのファイルを require する。

    spec のサンプル

    spec/foo_spec.rb

    # coding: utf-8
    require 'spec_helper'
    
    class Foo
      def self.foo
        "FOO"
      end
    
      def initialize(bar)
        @bar = bar
      end
    
      def bar
        @bar
      end
    end
    
    describe "Foo" do
      describe ".foo" do
        it "'FOO' を返す" do
          Foo.foo.should == 'FOO'
        end
      end
    
      describe "#bar" do
        context "'hoge' で初期化したとき" do
          before do
            @foo = Foo.new('hoge')
          end
    
          it "'hoge' を返す" do
            @foo.bar.should == 'hoge'
          end
        end
      end
    end
    

    以下のようにして動かす

    $ rspec spec/foo_spec.rb
    

    実行結果

    Foo
      .foo
        'FOO' を返す
      #bar
        new with 'hoge'
          'hoge' を返す
    
    Finished in 0.00814 seconds
    2 examples, 0 failures
    
  • devise と omniauth で facebook 認証をする手順

    rails アプリケーション作成

    $ rails new omniauth-devise-facebook-example
    

    Gemfile に以下を追記して bundle install

    gem "omniauth-facebook"
    gem "devise"
    

    devise のインストール処理

    $ rails g devise:install
    

    config/initializers/devise.rb に以下を追記(APP_ID と APP_SECRET には自分の facebook アプリの値をセットする)

    config.omniauth :facebook, "APP_ID", "APP_SECRET"
    

    モデル作成

    $ rails generate devise user
    

    必要なカラムを追加するためのマイグレーションを作成

    $ rails g migration add_fb_columns_to_users name:string fb_user_id:integer
    

    DB に反映

    $ bundle exec rake db:migrate
    

    app/models/user.rb の内容を以下のようにする

    class User < ActiveRecord::Base
      # Include default devise modules. Others available are:
      # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :omniauthable
    
      # Setup accessible (or protected) attributes for your model
      attr_accessible :email, :password, :password_confirmation, :remember_me, :fb_user_id, :name
    
      def self.find_or_create_from_auth_hash(auth_hash)
        user_data = auth_hash.extra.raw_info
        if user = User.where(:fb_user_id => user_data.id).first
          user
        else # Create a user with a stub password. 
          User.create!(:fb_user_id => user_data.id, :name => user_data.name, :email => user_data.email)
        end
      end
    end
    

    テスト用のコントローラーとルーティングとビューを用意

    $ rails g controller welcome index
    

    config/routes.rb に以下を追記

    root :to => 'welcome#index'
    

    app/views/welcome/index.html.erb の内容を以下のように

    <% if user_signed_in? %>
      Sign in as <strong><%= current_user.name %></strong>
      |
      <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
    <% else %>
      <%= link_to "Sign in with Facebook", user_omniauth_authorize_path(:facebook) %>
    <% end %>
    

    Facebook からのコールバックを受け付けるコントローラーの作成

    app/controllers/users/omniauthcallbackscontroller.rb というファイルを作成し、内容を以下のように

    class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
      def facebook
        @user = User.find_or_create_from_auth_hash(request.env["omniauth.auth"])
        sign_in_and_redirect @user
      end
    end
    

    public/index.html を削除し、サーバーを起動

    $ rm public/index.html
    $ rails s
    

    http://localhost:3000/ にアクセス

    "Sign in with Facebook" というリンクをクリックし認証を行う。

    参考

    その他必要だけどここでは取り上げなかったこと

    • コールバック時の params[:code] を使って API 呼び出しのためのアクセストークンを取得し、User のデータとして保存する必要がある
    • そして有効期限に応じてアクセストークンを再取得する仕組みも必要
  • 転職のお知らせ

    mediba →→ (^o^)/ →→ spice life

  • cheat sheet の Mac OSX 辞書データ作ったお

    チートシートをみんなで作って共有できる便利なものがあって、

    http://cheat.errtheblog.com/

    そこのデータを引っ張ってきて、Mac OSX に標準で入ってる Dictionary.app 用の辞書データを作りました。チートシートをさくさく検索できて便利です。

    Screenshot

    こちらがその辞書データになります: cheat sheets.dictionary.zip

    また、辞書データを作るにあたって、辞書データ作成のためのライブラリを ruby で作って gem にしました。osx_dict といいます。機会があればこちらもご活用ください。

    ちなみに、辞書データを作るスクリプトはこんな感じです: https://gist.github.com/1708517

  • ruby-debug の便利設定

    よく忘れるので

    ~/.rdebugrc

    set autolist
    set autoeval
    set autoreload
    
  • rbenv で ruby のバージョン管理をする(Mac)

    最近 rvm から rbenv に乗り換えた。

    https://github.com/sstephenson/rbenv

    rbenv というのは ruby のバージョンを管理するためのツール。

    セットアップ

    Mac なら Homebrew で必要なツールをインストールできる

    $ brew install rbenv
    $ brew install ruby-build
    

    ruby-build というのはいろんなバージョンの ruby をビルドするための便利ツールで rbenv はこれを利用して ruby のバージョン管理を行う。

    .bashrc とか .zshrc に以下を追記

    eval "$(rbenv init -)"
    

    使い方

    rbenv install

    以下のようにして任意のバージョンの ruby をインストールする

    $ rbenv install 1.9.2-p290
    

    readline を使いたい場合は brew で readline をインストールし、

    $ brew install readline
    $ brew link readline
    

    以下のようにして ruby をインストールする。

    $ CONFIGURE_OPTS="--with-readline-dir=/usr/local" rbenv install 1.9.2-p290
    

    rbenv rehash

    インストールしたら rbenv rehash しないといけない。gem install で入れた実行ファイルを使うためにも rbenv rehash しないといけない。これよく忘れる。

    $ rbenv rehash
    

    rbenv rehash が何を行っているかというと、 ~/.rbenv/shims というディレクトリに ruby 自体や gem でインストールした実行ファイルを起動するための実行ファイルを作ってくれる。

    rbenv global

    rbenv global で普段使う ruby のバージョンを指定できる。

    $ rbenv global 1.9.2-p290
    

    rbenv local

    rbenv local でそのディレクトリ以下で使いたい ruby のバージョンを指定できる。ディレクトリに .rbenv-version というファイルが作られ、そこに選択したバージョンが書き込まれる。

    $ rbenv local rbx-1.2.4
    

    以下のようにして rbenv local を取り消すことができる。

    $ rbenv local --unset
    

    rbenv shell

    rbenv shell で任意のバージョンの ruby を有効にした状態にできる。

    $ rbenv shell jruby-1.6.4
    

    rbenv versions

    rbenv versions で管理されている ruby のバージョンをリストアップできる。

    $ rbenv versions
      1.8.7-p357
    * 1.9.2-p290 (set by /Users/jugyo/.rbenv/version)
      2.0.0-dev
    

    rbenv version

    rbenv version で現在選択されている ruby のバージョンを表示できる。

    $ rbenv version   
    1.9.2-p290 (set by /Users/jugyo/.rbenv/version)
    

    rbenv which

    rbenv which でコマンドのフルパスを得られる。

    $ rbenv which irb
    

    rbenv whence

    rbenv whence でそのコマンドがどのバージョンの ruby にインストールされているか調べることができる(へー)

    $ rbenv whence rackup
    
  • Rails3 で resque を使う #2 - worker を daemon として起動し、monit で監視

    必要なライブラリのインストール

    daemon-spawn という gem を使って daemon 化します

    Gemfile に以下を追記し、

    gem 'daemon-spawn', :require => 'daemon_spawn'
    

    bundle install を実行

    daemon 用のスクリプトの作成

    ./script/resque_worker

    #!/usr/bin/env ruby
    
    require File.expand_path('../../config/application', __FILE__)
    Rails.application.require_environment!
    
    class ResqueWorkerDaemon < DaemonSpawn::Base
      def start(args)
        @worker = Resque::Worker.new('default')
        @worker.verbose = true
        @worker.work
      end
    
      def stop
        @worker.try(:shutdown)
      end
    end
    
    ResqueWorkerDaemon.spawn!({
      :working_dir => Rails.root,
      :pid_file => File.join(Rails.root, 'tmp', 'pids', 'resque_worker.pid'),
      :log_file => File.join(Rails.root, 'log', 'resque_worker.log'),
      :sync_log => true,
      :singleton => true
    })
    

    このスクリプトを使って worker の起動と停止が以下のようにして行える

    起動

    $ ./script/resque_worker start
    

    停止

    $ ./script/resque_worker stop
    

    monit で監視

    まず monit を適当にインストール(僕は yum で入れた)

    worker 監視用の monit 設定ファイルを作成

    /etc/monit.d/resque

    check process resque_worker
      with pidfile /var/[APP_NAME]/tmp/pids/resque_worker.pid
      start program = "/bin/sh -l -c 'cd /var/[APP_NAME]; RAILS_ENV=production ./script/resque_worker start'" as uid deploy and gid deploy
      stop program = "/bin/sh -l -c 'cd /var/[APP_NAME]; RAILS_ENV=production ./script/resque_worker stop'"
      if totalmem is greater than 300 MB for 10 cycles then restart  # eating up memory?
      group resque_workers
    

    monit を reload

    $ sudo /etc/init.d/monit reload
    

    試しに worker を kill してみて monit がそれを検知してくれるのを確認してみるとよい

    jugyo メモ

    monit って名前がかわいいね^^

    参考

  • Rails3 で resque を使う #1

    Rails3 だからといって別に特別なことはそんなに無いけど。

    あと、 redis は Mac だったら Homebrew 等で適当にインストールしといてください。

    インストール

    Gemfile に以下を記述し、

    gem 'resque'
    

    bundle install を実行

    いくつかのファイルを作成

    config/initializers/resque.rb

    Resque.redis = 'localhost:6379'
    

    lib/tasks/resque.rake

    require 'resque/tasks'
    task "resque:setup" => :environment
    

    試す

    (rails console 等で試すとよい)

    バックグラウンド処理の記述

    module Foo
      @queue = :default
    
      def self.perform(id)
        ...
      end
    end
    

    タスクの登録

    Resque.enqueue(Foo, 1)
    

    ワーカーの起動

    $ bundle exec rake resque:work QUEUE=default
    

    jugyo メモ

    resque は github みたいな大規模なシステム向けっていうイメージを持っていて、今のシステムにはオーバースペックかなと思ったけど、想像以上にセットアップが簡単でしかもほとんど迷うことなく使えるシンプルさで、良いんじゃないかと思ってる。

    参考

  • Amazon Linux での redis のインストール

    インストール

    $ wget http://redis.googlecode.com/files/redis-2.4.6.tar.gz
    $ tar xvzf redis-2.4.6.tar.gz
    $ cd redis-2.4.6
    $ make
    $ sudo make install
    

    サービスとしてセットアップ

    redis のソースの utils ディレクトリにセットアップ用のスクリプトが用意されているのでそれを使う。 Amazon Linux で使うにはスクリプトに少し手をいれる必要があった。

    パッチ: https://gist.github.com/1630767

    以下のようにパッチをあて、

    $ cd utils
    $ wget https://raw.github.com/gist/1630767/722302f7c20cff2ddf3e9e93cc2da551822be3d8/install_server.sh.diff
    $ patch < install_server.sh.diff
    

    スクリプトを実行

    $ sudo ./install_server.sh
    

    これで完了だ!

  • .ssh/config のひな形

    ~/.ssh/config

    Host foo
      HostName ec2-xxx-xxx-xxx
      User jugyo
      Port 2222
      IdentityFile ~/.ssh/jugyo.pem
    
  • Rails チェックリスト(作成中)

    モデル

    • アソシエーションが適切に定義されているか(:dependent => :destroy とか忘れがち)
    • バリデーションがちゃんと定義されているか(テストもちゃんと)
    • save, save!, create, create! を適切に使い分けるべし
    • transaction を適切に使用しているか

    コントローラー

    • RESTfull なルーティングになっているか
    • 認証、権限処理が before_filter 等で適切に行われているか
    • :id を変えることで別のユーザーのデータが見えてしまったりしないか

    セキュリティ全般

    • XSS(raw や html_safe を使っているところ注意)
    • ディレクトリトラバーサル(ファイルダウンロードするところ注意)
    • CSRF(form_tag や form_for を使っていれば通常は心配ない)
    • SQLインジェクション(基本、プリペアドステートメントを使う)

    jugyo メモ

    • 粒度がむずい
  • Railtie に関するドキュメントを訳した

    https://github.com/rails/rails/blob/master/railties/lib/rails/railtie.rb にある Railtie に関するドキュメントを訳した。 どう訳していいかわからないところは放置。

    rails/railties/lib/rails/railtie.rb

    Railtie は Rails フレームワークのコアで、 Rails に機能を追加したり初期化プロセスを変更するためのいくつかのフックを提供します。

    Rails の全ての主要なコンポーネント (Action Mailer, Action Controller, Action View, Active Record, Active Resource) は Railtie です。 これらはそれぞれ独自の初期化プロセスを行います。 This makes Rails itself absent of any component hooks, allowing other components to be used in place of any of the Rails defaults.

    Rails の機能拡張を作るために必ずしも Railtie の機能が必要というわけではありませんが、初期化時や初期化後に Rails フレームワークとインタラクトしたい場合は Railtie が必要になります。

    例えば、以下のような機能拡張を行う場合は Railtie が必要になります:

    • イニシャライザの作成
    • configuring a Rails framework for the application, like setting a generator
    • adding config.* keys to the environment
    • setting up a subscriber with ActiveSupport::Notifications
    • rake タスクの追加

    Creating your Railtie

    Railtie を使って Rails を拡張するために、あなたのエクステンションのネームスペース内で Rails::Railtie を継承した Railtie クラスを作ります。 このクラスは Rails のブートプロセスにおいてロードされなければなりません。

    The following example demonstrates an extension which can be used with or without Rails.

    # lib/my_gem/railtie.rb
    module MyGem
      class Railtie < Rails::Railtie
      end
    end
    
    # lib/my_gem.rb
    require 'my_gem/railtie' if defined?(Rails)
    

    Initializers

    あなたの Railtie から Rails のブートプロセスに初期化ステップを追加するには、 initializer ブロックを作るだけです:

    class MyRailtie < Rails::Railtie
      initializer "my_railtie.configure_rails_initialization" do
        # 初期化処理
      end
    end
    

    ミドルウェア等、アプリケーション固有の設定にアクセスしたい場合、ブロックはアプリケーションオブジェクトを受け取ることができます。

    class MyRailtie < Rails::Railtie
      initializer "my_railtie.configure_rails_initialization" do |app|
        app.middleware.use MyRailtie::Middleware
      end
    end
    

    最後に、 initializer のオプションとして :before と :after を使うことができます, in case you want to couple it with a specific step in the initialization process.

    Configuration

    Railtie クラスの内部で、全ての Railtie とアプリケーションで共有される config オブジェクトにアクセスすることができます:

    class MyRailtie < Rails::Railtie
      # ORM をカスタマイズ
      config.app_generators.orm :my_railtie_orm
    
      # to_prepare ブロックは production では一度、 development ではリクエスト毎に実行されます
      config.to_prepare do
        MyRailtie.setup!
      end
    end
    

    Loading rake tasks and generators

    Railtie が rake タスクを持っているなら、rake_tasks メソッドを使ってそれらをロードすることができます:

    class MyRailtie < Rails::Railtie
      rake_tasks do
        load "path/to/my_railtie.tasks"
      end
    end
    

    デフォルトでは、Rails はあなたのロードパスからジェネレータをロードします。 しかし、別の場所にらジェネレータを置きたい場合、Railtie の generators ブロックでそれらをロードさせるようにすることができます:

    class MyRailtie < Rails::Railtie
      generators do
        require "path/to/my_railtie_generator"
      end
    end
    

    Application, Plugin and Engine

    Rails::Engine はいくつかの初期化処理を伴った Railtie 以上のものではありません。 Rails::Application と Rails::Plugin はエンジンで、ここで説明した3つの設定全てを行えます。

    詳細については、それぞれのクラスのドキュメントを見てください。

  • showoff の使い方

    showoff というプレゼンツールを使ってスライドを作ろうかなと思ってる。

    showoff とは HTML ベースのプレゼンテーションツールで、 ruby で動作する。

    で、その使い方を調べた。

    インストール

    gem でインストールする。

    $ gem install showoff
    

    プレゼンテーションの作成

    showoff コマンドを作ってプレゼンテーションの雛形を作成できる。

    $ showoff create すごいプレゼン
    

    上記を実行すると以下のようなディレクトリ構成の雛形が作られるはずっす。

    すごいプレゼン
    ├── one
    │   ├── 01_slide.md
    └── showoff.json
    

    showoff.json の内容は以下のようになっており、

    { "name": "My Preso", "sections": [ {"section":"one"} ]}
    

    one という section があるというような記述になってる。

    one/01_slide.md が1セクションで、ここに Markdown でスライドの内容を書いていく。 ちなみに最初は以下のような内容になっている。

    !SLIDE 
    # My Presentation #
    
    !SLIDE bullets incremental
    # Bullet Points #
    
    * first point
    * second point
    * third point
    

    なんかいろいろ書き方あるんやろね。

    プレゼンテーションの実行

    以下のようにしてプレゼンテーションを実行する。

    $ cd すごいプレゼン
    $ showoff serve
    

    ブラウザで http://localhost:9090/ を開いてちゃんと動いているか確認してみよう。

    その他

    showoff コマンドには上記で紹介した create 以外にもいくつかのサブコマンドがあり、 それらを活用するとサクサクスライドをつくっていけるんじゃないかと思う。 なんかいろいろわかったらまたあとで書くかもしれない。

  • よく使う capistrano レシピ

    cap レシピのリストアップ:

    $ cap -T
    

    デプロイ:

    $ cap deploy
    

    このときサーバーの再起動も行われる

    マイグレーション実行:

    $ cap deploy:migrate
    

    デプロイ&マイグレーション実行:

    $ cap deploy:migrations
    

    ロールバック:

    $ cap deploy:rollback
    

    メンテナンスモード:

    $ cap deploy:web:disable
    

    メンテナンスモード解除:

    $ cap deploy:web:enable
    

    サーバー停止:

    $ cap deploy:stop
    

    サーバー起動:

    $ cap deploy:start
    

    サーバー再起動:

    $ cap deploy:restart
    

    アップデート(サーバーの再起動は行わない):

    $ cap deploy:update
    
  • Rails3 で exception_notification プラグインを使う

    Rails3 で exception_notification プラグインを使う方法について書いとく。といっても別に特別なことは何もないんだけど。

    ちなみに exception_notification プラグインは Rails アプリで例外が発生したときにメール通知するようにするためのもの。

    インストール

    Gemfile に以下を記述し bundle install

    gem 'exception_notification'
    

    設定

    exception_notification プラグインは rack ミドルウェアとして動作する。

    config/environments/production.rb 等に以下のような記述を追加するとよい。

    config.middleware.use(
      ExceptionNotifier,
      :email_prefix => "[Error] ",
      :sender_address => %{"notifier" <notifier@example.com>},
      :exception_recipients => %w{admin@example.com},
    )
    

    :ignore_crawlers オプションでクローラーによるアクセスの際の例外を無視することができる。

    :ignore_crawlers => %w{Googlebot bingbot}
    

    :ignore_exceptions オプションで通知対象から除外したい例外を指定することができる。

    :ignore_exceptions => %w{::ActionView::TemplateError}
    

    デフォルトで以下のエラーが通知対象から除外されるようだ。

    • ActiveRecord::RecordNotFound
    • AbstractController::ActionNotFound
    • ActionController::RoutingError
  • paper_trail めっちゃ便利や〜 - ActiveRecord でバージョニングを行うための Rails プラグイン

    paper_trail という Rails プラグインがあって、これを使うと ActiveRecord のモデルに対してバージョン管理的なことができるようになる。 モデルの変更履歴を残していってくれる。

    実際使ってみたら簡単で便利だったので紹介するお。 ちなみに Rails3 で試した。

    セットアップ

    Gemfile に以下を追記して bundle install を実行

    gem 'paper_trail', '~> 2'
    

    次に以下を実行

    rails generate paper_trail:install
    

    マイグレーションが作成されるので rake db:migrate を実行してスキーマを更新する。

    バージョニングを行いたいモデルに has_paper_trail というメソッド呼び出しを追加

    class Book < ActiveRecord::Base
      has_paper_trail
    end
    

    使い方

    > book = Book.first
     => #<Book id: 1, title: "bar", ...
    

    全バージョンの情報を取得

    > book.versions
     => [#<Version id: 1, item_type: "Book", item_id: 1 ...
    

    前のバージョンを取得

    > book.previous_version
     => #<Book id: 1, title: "foo"
    

    任意のバージョンを取得

    > book.versions[1].reify
     => #<Book id: 1, title: "foo", ...
    

    Version オブジェクトに対する操作

    > last = book.versions.last
    > last.previous
     => #<Version id: 1, item_type: "Book", item_id: 1 ...
    > last.next
     => nil
    > last.index
     => 1
    > last.previous.index
     => 0
    

    他にもいろいろ

    jugyo メモ

    • モデルの履歴情報は全て versions というテーブルに YAML としてシリアライズして保存されるようだ。
    • データが大量になるようなケースだと気をつけないといけないかもしれない。
  • Rails 3 / Sinatra 用のシンプルな認証ライブラリ - Sorcery の README 和訳(未完成)

    今作っている Rails 3 アプリケーションで Sorcery という認証ライブラリを使っています。 最初は devise を使っていたのですが、いかんせん使い方がわかりにくいので、それにかわるものとして Sorcery を選択しました。 選んだ理由は、比較的シンプルでわかりやすいので気持ちよく使える感じがするということです。

    今日はその Sorcery の README を和訳してみました(未完成)。

    Sorcery

    Rails 3 と Sinatra のための魔法のような認証。ActiveRecord と Mongoid をサポート。 restful_authentication、Authlogic、Devise にインスパイヤされています。 暗号化のコードはほとんどそのまま Authlogic から持ってきています。 OAuth のコードは OmniAuth と Ryan Bates のそれに関する railscasts にインスパイヤされています。

    哲学

    Sorcery は余分なものを取り除いた、必要最小限の認証ライブラリで、独自の認証フローを記述することができます。 それはいくつかの目標を念頭において設計されました:

    • Less is more - 覚える必要のある機能セット全体のパブリックメソッドが20個よりも少なければライブラリを使うのが簡単になります
    • ビルトインコードや生成されるコードが無い - あなたの MVC 構造の中でライブラリのメソッドを使用し、その他のことに患わされることがありません
    • 魔法ですが魔術(Voodoo)ではありません - ほとんどの開発者にとってライブラリをハックするのは簡単です
    • 混乱より設定(Configuration over Confusion) - 中央集中型(1ファイル)で、可能な限りシンプルで短い設定、かつシンタックスシュガーに溺れていません
    • MVC を明確に分離したままにしておいてください - DB はモデル、セッションはコントローラー、モデルはセッションを知ることはない。
    • うまくいっていればこれらが実装されているのですが、もしそうでなければお知らせください

    便利なリンク集:

    Railscast: http://railscasts.com/episodes/283-authentication-with-sorcery

    Example Rails 3 app using sorcery: http://github.com/NoamB/sorcery-example-app

    Example Sinatra app using sorcery: http://github.com/NoamB/sorcery-example-app-sinatra

    Documentation: http://rubydoc.info/gems/sorcery/0.7.0/frames

    github wiki のチュートリアルも参照してください

    API の要約

    以下はライブラリのメソッドの要約です。 ほとんどのメソッド名はそれ自体で意味がわかるようになっており、残りはコメントで説明しています。

    # core
    require_login # before filter
    login(username,password,remember_me = false)
    auto_login(user)# 認証情報無しでログイン
    logout
    logged_in?      # view で使用
    current_user    # view で使用
    redirect_back_or_to # ログイン後にユーザーが最初にアクセスしようとしていたページにリダイレクトさせたいときに使用する
    @user.external? # facebook/twitter などの外部ユーザーであることを表すために使用する
    User.authenticates_with_sorcery!
    
    # activity logging
    current_users
    
    # http basic auth
    require_login_from_http_basic # before filter
    
    # external
    login_at(provider) # ユーザーを認証のために外部プロバイダ(twitter など)に飛ばす
    login_from(provider) # 外部プロバイダのコールバックを元にログインを試みる
    create_from(provider) # ローカルDBにユーザーを作成する
    
    # remember me
    auto_login(user, should_remember=false)  # remember_me オプション付きで auto_login
    remember_me!
    forget_me!
    
    # reset password
    User.load_from_reset_password_token(token)
    @user.deliver_reset_password_instructions!
    @user.change_password!(new_password)
    
    # user activation
    User.load_from_activation_token(token)
    @user.activate!
    

    詳細な使用方法を知るためには github wiki のチュートリアルを参照してください。

    インストール:

    bundler を使用しているなら、最初に Gemfile に 'sorcery' を追加し、

    gem 'sorcery'
    

    bundle install を実行してください。

    それ以外の場合は単に gem install sorcery を実行してください。

    Rails 3 での設定:

    Rails 3 では以下のようにして initializer ファイルを作成します:

    rake sorcery:bootstrap
    

    これは config/initializers/sorcery.rb というファイルとして作られます。 中に書かれているコメントが知るべきことを教えてくれるでしょう。

    便利なように、 Sorcery は Rails のためのマイグレーションのジェネレータを含んでいます。 これは以下のようにして使うことができます:

    rails g sorcery_migration [サブモジュールのリスト]
    

    Note: session_timeout モジュールのためのマイグレーションはありません。例えば、コア機能だけを使うのであれば:

    rails g sorcery_migration core
    

    core と remember_me モジュール両方のマイグレーションを生成するには:

    rails g sorcery_migration core remember_me
    

    これらのマイグレーションはデフォルトのフィールドを使用します。 これらのマイグレーションを使うか独自のテーブルとフィールドを使うかは選べます。 Sorcery はあなたのアプリケーションのデータベース構造や命名について強制することはしません。

    そして、認証を使用するモデルに sorcery を追加します:

    class User < ActiveRecord::Base
      authenticates_with_sorcery!
    end
    

    Sinatra での設定:

    Sinatra の場合、initializer は手動で作る必要があります。 メインの app ファイルか require している別のファイルでそれを行うことができます(サンプルアプリの例を参照してください)。 コードは以下のようになります:

    Sorcery::Controller::Config.submodules = [] # specify here the submodules you want to include
    
    Sorcery::Controller::Config.configure do |config|
      config.session_timeout = 10.minutes
      ...
      ...
    
      config.user_config do |user|
        user.username_attribute_name = :email
        ...
        ...
    
      end
    end
    

    そして、上記のコードが有効になるように、Sorcery のコントローラーモジュールをインクルードする必要があります:

    include Sorcery::Controller::Adapters::Sinatra
    include Sorcery::Controller
    

    モジュールの全機能リスト:

    Core (see lib/sorcery/model.rb and lib/sorcery/controller.rb):

    • ログイン/ログアウト, ログイン時にユーザーがリクエストしていたページに戻すことが可能,未ログインユーザーのためのリダイレクトの設定
    • パスワード暗号化、アルゴリズム: brypt(デフォルト), md5, sha1, sha256, sha512, aes256, custom(yours!), none。ストレッチとソルトを設定可能
    • username, password, email の属性名を設定可能 allow multiple fields to serve as username.
    • 複数のフィールドをユーザー名として扱うことが可能

    User Activation (see lib/sorcery/model/submodules/user_activation.rb):

    (書きかけ。続きを読む