さとやn Blog

試合はRuby,勝負はC#!

RubyOnRails

Rails: fixture:loadでno(ナンバーの意)という列名に注意

Railsで

rake db:fixtures:load

を実行したら

PGError: ERROR: column "false" of relation xxxxx云々

そもそも"false" なんていうカラムはないんだけど、、、。

で、Fixtureの中身を確認してみたら
no(ナンバーという意味でそういう名前にしたのかと思われます)という列名を発見!
※fixutureはこんな感じ。

id: 1
name: satoyan
no: 
job: 
....

こいつが悪さをしていたようです。
使ってるDBはPostgresqlなのですが、boolean型のカラムに対して、no, 0, false, fというリテラルは false の意になるようで、どうもRailsの方でnoという文字列を列名なのにも関わらず勝手にfalseという文字に置き換えてくれてしまったようです。

と言うことで no あらため "no" とすることで解決。
最初、「はぁ?  falseなんて列あるわけねーだろ、、」とか言ってしばらく混乱してしまいました。


redmine でGmailを使う

新規にredmine を立てることになったのですが、メール送信はgmailを使いたい。
で、設定はどうするんだろう? ということで調べたらちゃんとredmineのガイドに書いてありました。

http://redmineblog.com/articles/setup-redmine-to-send-email-using-gmail/

action_mailer_optional_tls.git

以前にRailsでgmailの設定はしたことはあったのですが、redmineはメール設定を独自のyamlで管理しているらしく、どうせ書くことは一緒だろうと思っていたのですが、

action_mailer_optional_tls.git

というRailsのプラグインが必要になります。
まあ、設定は一緒なんですが、、。
 
 

capistrano で svn+ssh する場合

Subversinoへのアクセスにsvnやhttpではなくsvn+sshプロトコルを使用している場合、どうもCapistranoがしっかりやってくれない。
deploy.rbに配置先からSVNサーバーへのsshのパスワードを指定する方法がないから、のようなのです。

鍵認証にして、ssh-agent立てるかパスワードなしの鍵ファイルにするのが簡単なのでしょう、きっと。

eval `ssh-agent` 

でエージェントを起動して

ssh-add 鍵ファイル

で 鍵ファイルを登録してやればOKのよう。
agent終わらす場合は

eval `ssh-agent -k`。

また、

ssh-agent bash(とかzshとか)

ってやると、バックグラウンドで起動し続けて、シェルを終了すると自分も終了してくれるようです。

でも、どっちも面倒なので、パスワードなしの鍵ファイルにしてみる。

すでに鍵ファイル使ってるので、

ssh-keygen -p

でパスワード変更して、無事

cap depoy

正常終了!
 
あんまり sshでsvnってやらないのかな、、、。
俺様認証局立てて、SSLでHTTPよりは全然簡単だと思う。

 

WindowsでRails開発 ー遅いー

WindowsでRails開発をやるときに私がぶち当たった問題。

  • Railsの起動が遅い(20秒くらいかかる)。これはテスト駆動開発においては致命的なスピードです。テスト実行する度に20秒待たされるわけですから。
  • Windowsのコマンドプロンプトの文字コードはSJISだけど、Railsは基本UTF8なので RSpec等のテスト実行時にメッセージが文字化けするので、即座にログメッセージを確認できない。コマンドプロンプトの文字コードを変更するとRSpecで不具合が発生したような、、、。
  • 同じくWindowsとLinuxのコマンドプロンプトでは使い勝手に雲泥の差がある。タブ、/、ファイルに実行属性をつけられないため、いちいち 先頭に ruby と打つしかない、など、、。
  • gemなどで公開されている便利なライブラリ、ツールがWindowsに対応してないものがある。ディプロイツールCapistranoが使えないは致命的。
  • エディタTextMateが使えない。eTextEditorはいいのですが、完全にTextMateのようにはいかない。viは嫌だ。
他にもあるかもしれませんが、とりあえずすぐに思い浮かぶのはこんなところです。
結論としては、WindowsでRailsの開発をやるべきではない、ということになるのですが、実際の現場ではそういうわけにも行きません。
仕方ないので、私は、
  • エディタ: TextMateクローンのeTextEditor。EclipseやNetBeansなどのIDEはRailsではデメリットのほうが多い。
  • 実行環境: cygwin上にRails環境を構築。ターミナルソフトはPoderosa
  • 起動の遅さ: なんとしてもテスト時の時間は短くしたいのでSpecServerを立てる。gemでsporkというものに変わってしまっている。
これで何とか、それなりに開発出来てます。
ただ、それでも、eTextEditorはRSpecバンドルでのファイルナビゲーションが正常に機能しなかったり、spork立てても ./script/generate など、rspec以外のRails起動は相変わらず遅いなど、不都合はあります。
 
あと、実際にやってたのですが、エディタはWindowsでeTextEditorを使うのは同じですが、実際のRails環境はLinux上に構築して、FTPもしくはSambaでファイルにアクセスしてソース編集、みたいなこともやってました。ただ、それだと、エディタのファイルナビゲーションが全く機能しない(FTP)、異様に時間がかかる(Samba)で、完全に解決には至りませんでした。
エディタはVIでいい、という人ならいいんでしょうけど、やっぱりTextmateで作りたいですから、、。 IDEはねぇ、Railsでは必要性が分からない。

ActiveRecord 中間テーブルを使用する場合のメモ

これもいつも忘れてしまうのですが、
たとえば、とあるブログサービスで
Member : 会員
Article : ブログ記事
という2つのモデルがあり、
ここにできれば記事ごとに会員を関連付けて、その記事の「読者」という形でデータを持たせたいと思った場合は、中間テーブルを使用すると思うのですが、Railsの場合はこんな感じでやります。
 
中間テーブルのモデルとして、ArticlesMember モデルを定義します。
※別に名前はこれじゃなくてもいいのですがRailsの規約に従ってそうしました。
 
基本的にこいつはMemberとArticleのIDを持つ中間テーブルです。
※中間テーブルのために新しいモデルを定義する必要があるのか? と思うかもしれませんが、ここに例えば、記事に対する読者の評価(よくある星マークみたいなヤツ)とか他の属性も持たせたくなるケースもよくあると思います。そうするとやっぱりモデルとして持たせるのは正解だと思います。
 
それぞれのモデルは多分こんな感じ。
has_manyとthroughを使います。 
# 読者は会員と記事に属している
class ArticlesMember < ActiveRecord
  belongs_to :member
  belongs_to :article
end

#会員は中間テーブル readers(Readerモデル)を通して読者になっている記事情報(Articleモデル)を持っている
class Member < ActiveRecord
  has_many :articles_members
  has_many :articles, :through => :articles_members, 
end

# 記事は同じく 中間テーブル articles_members(ArticlesMemberモデルを通して会員データ(Memberモデル)を持っている
class Article < ActiveRecord
  has_many :articles_members
  has_many :members, :through => :articles_members
end
これで簡単に記事データから読者としての会員情報にアクセス出来ます。 こんな感じ。
# とある記事の全読者のフルネームを表示
article = Article.find(1)
article.members.each do |member|
  p "この記事の読者は #{member.full_name} さんです"
end
article.members という名前で読者情報にアクセスしていますが、それは単に読者=会員=Memberモデルだから、members という名前になっているだけです。 これをもっと直感的に readers(読者なんだから)としたい場合は、 source オプションを使用すればOKです。
class Article < ActiveRecord
  has_many :articles_members
  has_many :readers, :through => :articles_members, :source => :member
end

#すると、同じように、

article = Article.find(1)
article.readers.each do |reader|
  p "この記事の読者は #{reader.full_name} さんです"
end
こんな感じになります。
もう忘れないでしょ。 

Railsでネストしたモデルのformを使う: fields_for, accepts_nested_attributes_for

今日も、あれどうやるんだっけ? となってしまい、いつも忘れてしまうので、書いとこ。

Railsでは form_for ビューヘルパーを使用すれば、特定のモデルのHTMLフォーム要素の生成と、POSTされたデータからモデルを生成する処理が非常に楽になります。
 
def create_member
  m = Member.create(
    :email => params[:email], 
    :job => params[:job], 
    :sex => params[:sex])
end
こんな処理が、
def create_member
  m = Member.create(params[:member])
end
で済んでしまいます。
まあ、ここまでは別に問題ないのですが、例えばMemberの住所を別のモデルで定義している場合はどうすんだけっけ? と言うケースが多々有り、その都度忘れてるので調べ直してました。

まず、モデルの方に accepts_nested_attributes を宣言します。
これをやらないとネストした属性情報を受け取ってくれないようです。この場合だとMemberモデルがAddressモデルをもっているので、Memberモデルクラスに
accepts_nested_attributes_for :address, :allow_destroy => true
と宣言させて、
ビューの方は、
<% form_for @member do |f| %>
  email: <%= f.text_field :email %> <br/>
  job: <%= f.text_field :job %> <br/>
  sex: <%= f.text_field :sex %>
  <!-- ネストした住所情報 -->
  <% f.fields_for :address do |f2| %>
    都道府県: <%= f2.text_fieldf :prefecture %>
    市町村: <%= f2.tet_field :city %>
    .....そんな感じで
  <% end %>
<% end %>
fields_for を使えば良いわけですね。

これを知らないときは、結局form_forは使用せずに、自前で全部フィールド書いて、コントローラーでも一個ずつ設定してました。
 

複数バージョンのRubyを安全に仕様するRVM

何やらRVMという複数バージョンのRubyの管理をしてくれる仕組みがあると言うことを、Rails3のスクリーンキャストで知ったので、中々試す気になれなかった1.9系をインストールしてみました。

RVMのサイト
http://rvm.beginrescueend.com/

ドキュメントを見ると複数のインストール方法があるようですがGit推奨のようなのでGitでインストール。
http://rvm.beginrescueend.com/rvm/install/

mkdir -p ~/.rvm/src/ && cd ~/.rvm/src && rm -rf ./rvm/ && git clone --depth 1 git://github.com/wayneeseguin/rvm.git && cd rvm && ./install

BootstrapScriptてなものも用意されていて、それをそのままターミナルに貼りつけると、
Git, Rvm, そしてRubyの1.8.6,1.8.7,ree,1.9.1,jruby,rbx を一気にインストールしてくるようです。やってませんが、、、。reeって何?

で、Rubyのインストール。
rvm install 1.9.1 
で任意のバージョンのRubyインストールが可能なようです。

rvm listとやるとこんな感じになります。
02)


system [ x86_64] ってのは、普通に自分でソースからコンパイルしてインストール済みだったRubyのことです。

でバージョンを切り替えるには、
rvm 1.9.1
とやるだけでOKです。
13)

切り替え前のバージョンが 1.8.7 で、
切り替え後に 1.9.1になっているのがわかるかと思います。

ここで切り替えたRubyはあくまで現在のターミナルのセッションの間だけで有効なので、新規にターミナル開くと、またRuby1.8.7に戻ります。常に特定のバージョンを指定したい場合は、--default オプションを指定するようです。

rvm 1.9.1 --default

とやると毎回Ruby1.9.1が動くようです。
で、もともと入っていたRubyに戻したい場合は、
rvm system --default とやれば元に戻ります。
48)


 gem独立しているので、
.rvm/rubies/ruby-1.9.1-p378/bin/gem
必要なものを再度インストールします。
とりあえず、Rails3をやってみようかな、、、。
 

TextMateでRSpecを実行

RSpecやる時はいつもターミナルでコマンド叩いてやっていたのですが、先日RSpecコードをTextMateで開いた状態で、あやまって Command + R を押してしまったら、テストが開始されてHTMLフォーマットで結果が表示されました。
こんな感じ。
別に私的な開発なのでテスト内容が見れても構いません。
55)

いいかもしれない。
普段は、./script/spec -cfs <target_file or directory>
とかやってるのですが、これはこれでいいかもしれません。
更に、control + shift + ↓ でRSpecファイルとそのテスト対象のファイル(controller,mode,etc)を行き来できます。これもかなりいいですね。
shift + alt + command + ↓
はSpecに対応してないので重宝しそうです。

ちなみに control + shift + R で Rakeタスクも実行できます。
この画面でタスクの検索も出来るともっと便利なのですが、,。
05)

content_for でデフォルトを設定する場合

ページ毎にmetaタグのキーワードなどを変更したい時などは、content_for が便利ですが、でも全てのビューでそれを指定するのは面倒だから、content_forが用意されている時だけ、それをレンダリングして、用意されてなければ規定のものを使用したい。
で、どうやるのかな、と思いいつもお世話になるAPIビューア、
http://apidock.com/rails
で調べたら、単純にif文でいけるのですね。
    1     <% if yield :meta_keywords %>
2 <%= yield :meta_keywords %>
3 <% else %>
4 <meta name="keywords" content="これは規定のキーワード" />
5 <% end %>
6

    1 
2 <% content_for :meta_keywords do %>
3 <meta name="keywords" content="hoge" />
4 <% end %>
5
6

更に発見してしまったのですが、
content_for って複数指定したら、単純に追記されていくのですね。


    1 
2 <%= yield :test %>
3
4 <% content_for :test do %>
5 hello
6 <% end %>
7 <% content_for :test do %>
8 world
9 <% end %>

としたら、単純に hello worldと表示されます。

i18n localeファイルを生成してくれる gem plugin

Rails2.2(だったような)からはi18n対応と言うことで、今までは勝手に英語で表示されていたよなメッセージを簡単に日本語化できるようになったようで、
config/locales/ 下に
en.ymlとか
ja.ymlとかすればいいとのこと。
で、その辺を自動的にやってくれるプラグインがありました。
しかも、モデルの属性名とかも翻訳してくれると言う優れものです。
生成されたものをザーと見ていって、おかしな部分だけ直せば済むわけですから、0から自分で書くのに比べれば、かなり楽です。

サイトはこちら
http://github.com/amatsuda/i18n_generators

インストール
sudo gem install amatsuda-i18n_generators

./script/generate i18n_locale ja
とやると、こんな感じで、config/locales/ja.yml が作成されます。

# Japanese translations for Ruby on Rails
# by Akira Matsuda (ronnie@dio.jp)
# AR error messages are basically taken from Ruby-GetText-Package. Thanks to Masao Mutoh.

ja:
date:
formats:
default: "%Y/%m/%d"
short: "%m/%d"
long: "%Y年%m月%d日 (%a)"

day_names: [日曜日, 月曜日, 火曜日, 水曜日, 木曜日, 金曜日, 土曜日]
abbr_day_names: [日, 月, 火, 水, 木, 金, 土]

month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月]
abbr_month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月]

order: [:year, :month, :day]

time:
formats:
default: "%Y/%m/%d %H:%M:%S"
short: "%y/%m/%d %H:%M"
long: "%Y年%m月%d日(%a) %H時%M分%S秒 %Z"
am: "午前"
pm: "午後"



更に、
./script/generate i18n_translation ja
とやると、モデルの属性名を翻訳してくれます。

      member: 
pkid: "Pkid" #g
user_name: "ユーザー名" #g
application_name: "アプリケーション名" #g
email: "Eメール" #g
comment: "コメント" #g
password: "パスワード" #g
password_question: "パスワードの質問" #g
password_answer: "パスワードの解答" #g
is_approved: "承認される" #g

「承認される」ってのはおかしいので直す。
プロフィール

さとやn

C#が好きだけど仕事はRubyばかりな開発者。
最近はDockerとか関数型言語とかAngularJSにハマっている。
武蔵小杉とか田町とか柏とかに出没。

QRコード
QRコード
  • ライブドアブログ