カラム名にtypeが使えない

なぜかDBでtypeのカラムの値が取得できないと思っていたら、カラム名にtypeは使えないみたいです。

typeとか普通に使いそうなのに・・・
値が取得できないだけでエラーとかでてこないので、全然原因がわからなかった。
他にも以下の名前は使えないらしい。

  • attribute
  • class
  • clone
  • connection
  • display
  • errors
  • freeze
  • hash
  • inspect
  • load
  • logger
  • methods
  • toggle
  • type
  • validate

Railsのi18n_generatorsのために苦戦

世間は大晦日でしたが今日は一日中i18nに苦戦。。。
そもそも日本語化のためにgettextを入れようとしてたんですが、rails2.2では入れるのは難しく、代わりにi18nで日本語化ができるということに気づくまでに3時間ほどかかった。

そしてここを参考にi18n_scaffoldできた!と思ったら一部おかしい。

さらに調べると同じ症状ではまっている人を発見。
そしてrubyを1.8.7にしたわけですが、またエラー。

$ ruby script/generate i18n_scaffold note title:string body:text

でscaffoldした後にサーバーを起動してhttp://localhost:3000/notesにアクセスすると、以下のログがでてサーバーが止まってしまう。。。

/Users/mikamishunsuke/.gem/ruby/1.8/gems/sqlite3-ruby-1.2.4/lib/sqlite3_api.bundle: [BUG] Bus Error
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.5.1]

Abort trap

どうももともとデフォルトで入ってたruby(つまり/usr/binに入ってるやつ)を使っていたんですが、今回アップデートしてパスが変わったせいみたいです。

$ which ruby
/usr/local/bin/ruby
$ which gem
/usr/local/bin/gem
$ which rails
/usr/local/bin/rails
$ which sqlite3
/usr/bin/sqlite3

それで

gem install sqlite3-ruby -- --with-sqlite3-include-dir=/usr/local/sqlite3/include --with-sqlite3-lib-dir=/usr/local/sqlite3/lib

をやってみたらなんとかできるようになりました。
しかしvalidatesのエラーメッセージが表示されないエラーの原因は別の所にあったみたいで。。。
別にruby1.8.6でもいけたのかも。
疲れた。。。

ruby-modeの機能

ruby-modeのインストール方法についてはあちこちで書かれてるけど、ruby-modeの機能についての参考になるものが少ない。
ruby-mode.elを自分で読んで理解しろということなのか??

とりあえずコマンドについてruby-mode.elの86行あたりからの

(if ruby-mode-map
    nil
  (setq ruby-mode-map (make-sparse-keymap))
  (define-key ruby-mode-map "{" 'ruby-electric-brace)
  (define-key ruby-mode-map "}" 'ruby-electric-brace)
  (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
  (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
  (define-key ruby-mode-map "\e\C-b" 'ruby-backward-sexp)
  (define-key ruby-mode-map "\e\C-f" 'ruby-forward-sexp)
  (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
  (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
  (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
  (define-key ruby-mode-map "\e\C-q" 'ruby-indent-exp)
  (define-key ruby-mode-map "\t" 'ruby-indent-command)
  (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
  (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
  (define-key ruby-mode-map "\C-m" 'newline))

コマンドはこれしかないのか。C-aとかはデフォルトと何が変わっているんだろうか。
とりあえず使えると思った機能は、

  • \C-c\C-eでendを挿入
  • \C-jで改行してインデント
  • \C-mで改行

くらいかな。改行してインデントはかなり便利!
enter押すよりも楽だし。

まあ、rubyで書いてくうちにもっと有り難さがわかってくるんだろうか。

.emacsの設定

今まであまり設定せずにemacs使って来たけど、これからずっと使っていくので設定についてちゃんと調べてみた。

シフト押しながらキー移動で範囲選択とかも出来るようで便利。
今の.emacsの内容は

;;ロードパスを追加
(setq load-path(cons "~/emacs" load-path))
(setq load-path(cons "~/emacs/emacs-rails" load-path))
;;行と列番号を表示
(line-number-mode t)
(column-number-mode t)

;;起動時の画面を消す
(setq inhibit-startup-message t)

;;シフト押しながらキー移動で範囲選択
1(setq pc-select-selection-keys-only t)
(pc-selection-mode 1)

;;透明にする。
(add-to-list 'default-frame-alist '(alpha . (0.85 0.85)))

;;対応する括弧を光らせる
(show-paren-mode 1)

;;ruby-modeを使用
(setq interpreter-mode-alist
      (cons '("ruby" . ruby-mode) interpreter-mode-alist))
(setq auto-mode-alist
      (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
(autoload 'ruby-mode "ruby-mode" nil t)

;;rails.elを読み込む
(defun try-complete-abbrev (old)
  (if (expand-abbrev) t nil))

(setq hippie-expand-try-functions-list
      '(try-complete-abbrev
        try-complete-file-name
        try-expand-dabbrev))
(setq rails-use-mongrel t)
(require 'rails)

ruby-modeを入れてみたはいいが使い方がよくわからん。
勉強しないと。
rails.elの機能はこちらを参考にさせてもらった。

Railsで Status: 500 Internal Server Error. wrong number of arguments (1 for 0) ...

自分でメール配信システムを作ろうとして、

ruby script/generate controller delivery index form confirm send

みたいな感じでコントローラを作ったらhttp://localhost:3000/deliveryにアクセスする時に500errorが発生。
どうやらコントローラのメソッド名にsendを使うとhttp://localhost:3000/delivery/sendだけじゃなくてコントローラ全体が500errorになるようで。

たぶんsend以外にも使えない名前があるんだろうなぁ

RailsのActionMailerでGmailのsmtpサーバーを使ってメール送信する。

えー、10章と11章は問題なかったので飛ばしますw
そして12章からはテストに入って行ってますが、何か作っていかないとモチベーションが保てないので次はメールの送信やってみます。

メール送信できれば実際に使えるシステムを作れそうだ。
本番環境に移す方法がまだよくわかってないけど。

まずは開発環境だと実際にメールを送れなくてもエラーが出ないので、
/config/environments/development.rbの下の行をtrueにする。

config.action_mailer.raise_delivery_errors = true

そしてすばらしいコードがあったので使わせてもらいました。
http://www.prestonlee.com/archives/63

以下のコードを書いてlib/smtp_tls.rbに保存します。

require "openssl"
require "net/smtp"

Net::SMTP.class_eval do
  private
  def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    check_auth_args user, secret, authtype if user or secret

    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout

    check_response(critical { recv_response() })
    do_helo(helodomain)

    if starttls
      raise 'openssl library not installed' unless defined?(OpenSSL)
      ssl = OpenSSL::SSL::SSLSocket.new(sock)
      ssl.sync_close = true
      ssl.connect
      @socket = Net::InternetMessageIO.new(ssl)
      @socket.read_timeout = 60 #@read_timeout
      do_helo(helodomain)
    end

    authenticate user, secret, authtype if user
    @started = true
  ensure
    unless @started
      # authentication failed, cancel connection.
      @socket.close if not @started and @socket and not @socket.closed?
      @socket = nil
    end
  end

  def do_helo(helodomain)
    begin
      if @esmtp
        ehlo helodomain
      else
        helo helodomain
      end
    rescue Net::ProtocolError
      if @esmtp
        @esmtp = false
        @error_occured = false
        retry
      end
      raise
    end
  end

  def starttls
    getok('STARTTLS') rescue return false
  return true
  end

  def quit
    begin
      getok('QUIT')
    rescue EOFError
    end
  end
end

そしてconfig/environment.rbの設定は


require "smtp_tls"

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:authentication => :plain,
:user_name => "username@gmail.com",
:password => 'password'}

あとは普通にメール送信したらできました。
注意は、開発環境でもconfig/environment.rbの更新は再起動しないといけないみたいです。


ーーー追記ーーー

しばらくしてから同じようにメール送信しようとしたら

wrong number of arguments (3 for 2)

/lib/smtp_tls.rb:8:in `check_auth_args'

というエラーが出て送信できなかった。
   
\lib\smtp_tls.rb の8行目で、

check_auth_args user, secret, authtype if user or secret を
check_auth_args user, secret if user or secret
のように、check_auth_args 呼出時のパラメタ authtype を削除したらメール送信できました。

前にこれで送信できた時はrubyのバージョンが1.8.6で今は1.8.7なのでその違いなのかもしれません。

RailsによるアジャイルWebアプリケーション開発第9章

いつも参考にしてる日記を見るとajaxのことについてあるが、第1版を使ってるので内容が違っているようだ。

まずデータベースの作成は8章でやったように自分で読み替えて作成。

フォームの作成でNoMethodError

undefined method `start_form_tag' for #<ActionView::Base:0x1e79c20>

調べてみると

<%= start_form_tag %>
<%= end_form_tag %>

<% form_tag do %>
<% end %>

に変更になったらしい。
こちらを参考にしました。

これを直す時に<% に直すのを忘れて <%= にしていてなかなか気づかなかった。
それで調べたらrubyのコード開始タグと終了タグにもいろいろ表記があることを今更知る。<% ... %>だと表示はされないけど改行や行頭に空白が入ったりする。

   <% ... -%>
Hello

のようにかくと実際は

   Hello

という改行して行頭に空白が入った出力になるのでそれをなくす表記もあります。
対応は以下。

表記 コード実行 表示 行頭空白 改行
<% ... %> -
<%= ... %>
<%- ... %> - -
<% ... -%> - -
<%- ... -%> - - -
<%# ... %> - - -
まあ、ソースに改行が入ってもブラウザで見ればほとんど影響はないんだろうけど念のために。