2007年8月6日月曜日

Railsでの新規開発の流れ

Railsを利用しての新規開発の流れをまとめておく。
前提としては、
 ・どのようにデータを保持するかModelの設計は完了している。
 ・Railsを起動してのモックアップは作成済み
 ・プラグイン導入済み、設定ファイルの設定も完了済み
とします。(つまり、すでにコードが打てる状態とする)

大まかな流れとしては、
1、Model生成とMigrateによるDB作成
2、Scaffoldの作成(今回はスペジェネを利用)
として、細かい調整が可能になる状態までをまとめておきます。

1、Model作成
  >ruby script/generate model XXXXXX
Railsの1.1以上だと、この時点でmigrateも生成される。
  なおXXXX部分は、1文字目を大文字にして単数形で書く。

2、Migrate の作成
  1で出力されているログを見て、Migrateファイルの名前を見つけて編集する。
  なお、型の対応は以下のとおり。

  :string - varchar(255)
  :text  - text
  :float  - float
  :integer - int(11)
  :datetime- datetime
  :date  - date

3、Migrateの実行
  既に実行している場合、DB上にどのバージョンまで実行したか
  保存されているので、追加の場合も以下のコマンドで大丈夫。
  >rake db:migrate

4、スペジェネを使う。
  scafflodの代わりに「スペジェネ」を利用。
  > script/generate special コントローラー名
  コントローラー名は単数形で。

とりあえず、こんな感じで。


 

2007年7月26日木曜日

Form結果のpagenate

以前このブログにpagenateをまとめたが、その後ちょっと問題が
あることが解りました。

<状況>
複数のフォームを持つトップページを作り、1コントローラーにて
複数のメソッドにて受付を行なう。
結果表示はlistのテンプレートを利用しレンダリングさせる。

<問題点>
ユーザー入力なしのpagenateの場合はGETの引数にpageというのがあれば
そのページが表示されて終わりでいいのですが、
Formからの入力後のpagenateの場合、ユーザー入力を引き継ぎつつ
次ページへのリンクを作る必要があります。
以前は
<%= link_to_unless(params[:page].to_i == page.number, page.number, {:params => params.merge('page' => page)}) %>
としていました。
問題は「params.merge」です。
この実行結果に、text_field( :theme, :title) として作られた入力の結果が流れると
theme=title入力
というようにmergeされます。
正しくは「theme[title]=入力」とならないと、メソッドで正常に受け取りが出来ないです。

<解決策>
かっこいい方法が思いつかなかったので、とりあえず下記のように逃げました。

controller
@link_hash = {'theme[title]' => params[:theme][:title]}

View
params.mergeを@link_hash.mergeにする。

もしユーザー入力が無かったという状態も引き継ぐとなるとGETには
theme[title]=
となって欲しいです。
しかし、これは入力が無いためにparamsではnilになります。
そこでcontroller冒頭にて
params[:theme][:title] = "" if params[:theme][:title] == nil
として無理やりnilを回避しました。

ちょっとかっこよく無いのですが、良い案が思いつかないので
とりあえずこれで回避です。

2007年7月20日金曜日

RailsMyAdmin

Railsのプラグインで便利なものがMoonGiftで紹介されていたので
早速試しました。

「RailsMyAdmin」

<機能>
phpMyAdminと同じく、Railsアプリで参照されているDBを
直接操作する機能が提供されます。

<導入手順>
RailsMyAdminはプラグインです。
導入したいアプリで以下のコマンドを打ちます。(Linuxの前提)
プロキシサーバを利用している場合のみ、以下のコマンドを
入力してください。
> set http_proxy=http://proxy.server.jp:8080
> ruby script/plugin install http://railsmyadmin.googlecode.com/svn/trunk/my_admin/
> ruby script/generate my_admin
次にenvironment.rbに以下の3行を追加します。
※提供元の資料からコメント部分を割愛したものです。
## MY ADMIN CONFIG
require 'my_admin/my_admin_tool'
MY_ADMIN_GLOBALS = {:all_models => true, :confirm_destroy => false}
MY_ADMIN_AUTH = Proc.new { |c| c.send('admin_logged_in?') }
最後にapplication.rbに以下のメソッドを追加します。
def admin_logged_in?
return true
end
もし、この機能にパスワードを付けて利用したい場合は、上記のメソッド内で
判定を行ないます。

これで利用の準備はOKです。
http://localhost:3000/my_admin/main
にアクセスすると利用できます。

このプラグインの目玉の一つである「Spy」について。
DBを監視し、データの移り変わりをブラウザで見るという機能です。
この機能を使いたいテーブルには「created_at」列が必要になります。
「created_at」が無いとエラーになりますので、作っておいてから利用しましょう。

提供元: RailsMyAdmin

2007年7月10日火曜日

Rails Tips

細かいTipsが溜まったのでまとめておきます。

1、Distinct
<参考> リンク

SQLのDistinctを使いたい時、find_by_sqlを使ってましたが
やはりちゃんとFindで出来る事が判明。
>> RubricksUser.find(:all, :select => 'distinct *')
SELECT distinct * FROM rubricks_users
>> RubricksUser.count(:distinct => true, :select=> 'id')
SELECT count(DISTINCT id) AS count_id FROM rubricks_users

とのこと。 findのselectがポイントですな。


2、modelとcontrollerの図
これを追加すると、モデルの関係性やControllerの関係性が図になる。
大変便利だし、scaffoldで生成されて使っていないメソッドなどを
整理しないと!と思うので良いと思います。

<参考> RailRoad

なお、「RailRoad as a rake task」という部分のスクリプトを書けば
Rakeで生成出来ます。

インストール前に「Graphviz」のインストールをしておきます。
Ubuntuの場合は、システム>システム管理>Snapticパッケージマネージャより
検索をするとパッケージがありますので、そちらを使うと楽です。

生成されるSVGというファイルは、中を見ると解りますが文字ベースです。
見るときはブラウザにドロップすると見られました。

3、paginageでページ数表示
paginateで出力する場合、画面の一番下にナビゲーションをつけたくなります。
前と後とページ番号の列挙のサンプル

<%- if @theme_pages.current.previous -%>
<%= link_to '前の30件', { :page => @theme_pages.current.previous } %>
<%- else -%>
前の30件
<%- end -%>
|
<%- for page in @theme_pages -%>
<%= link_to_unless(params[:page].to_i == page.number, page.number,
{:params => params.merge('page' => page)}) %>
<%- end -%>
|
<%- if @theme_pages.current.next -%>
<%= link_to '次の30件', { :page => @theme_pages.current.next } %>
<%- else -%>
次の30件
<%- end -%>

今回はここまで。

2007年7月5日木曜日

LinuxでのRails環境構築

windowsですとインスタントRailsがあるので、
開発環境が無いところからRubyのインストールを含む
環境構築が簡単に行なえます。

ついにLinuxでも出ました。

Rails For Linux

まだ試してませんが、これは良さそうですね。

ViewのDRY

Viewを書いていると、他のControllerのAction結果を使いたいことが
多々あります。これをコピペでやってしまうと、DRYが守れません。

ということで、かるくまとめ。

<Viewで他のAction結果を読み込む>
  Viewでrender_componentを使います。
  <%= render_component :controller => "documents", :action => "list", :id =>@sum.id %>
  これで、他のViewにて違うControllerのアクション結果を表示出来ます。
  注意点は、呼び出される側のActionで
  render :layout => false
  を実施しておくこと。
  これをしないと<html>も出て来てしまいます。

  ということで、この方法を使えば複数のコントロールにあるshowのような
  詳細表示部分を、1ページにまとめるなどが簡単に行なえます。便利!

<Action内で、他のAction結果を受け取る>
  Viewで使うrender_componentですが、これをControllerのActionで呼び出して
  出力されるHTMLを別のActionから返す場合
  つまり
   -->  Action1(受付窓口) --> Action2(処理とHTML生成)
という風にリクエスト内容を送って、Action2の結果をAction1で受け取ってから
  リクエスト元に返したい場合はrender_component_as_stringを使います。
  これを使うと、評価結果が文字列として取得出来るので、さらにAction1で追加を
  書いてから送り返すなども可能です。

この2つを使うことでViewのDRY化がだいぶ進むと思ってます。
概念的に上位のモデルのShowにて、has_manyやhas_oneに
なっている下位のモデルを取得し、そのIDを渡して下位のControllerの
Showを呼び出します。
その結果をはめ込んで送る・・・・というのを繰り返せば、それぞれのモデルの
Showを連携させて1ページを合成することができるし、
ShowからAJAXでEditやDestroyを呼び出す様に変えると
ユーザーの見た目は1つのレコードを編集しているつもりでも、
DB上は複数のテーブルにまたがって修正していることになり、
かつそれらを別々のControllerに置いておけます。

この二つをうまく使うのがViewのDRY化を進める上で不可欠かと思います。
もちろんpartialで逃がすのも手ですが、Partialは一つのモデルに対して
DRYを促進する機能だと解釈してます。

RailsでのAJAXデバッグ

RailsのAJAXサポートものを使う時に、ちゃんと
Actionno結果が評価されているかが心配になります。

ブラウザの「ソースを表示」では、一番最初に送ったHTMLしか
表示してくれないので、変化した後の状態がわかりません。
ということで、FireFoxのアドオン「Firebug」を使ってみました。

まだ使い込みが甘いので深い使い方は説明出来ませんが、
とりあえず入れただけでも以下の効果がありました。

1、ソースをdiv単位で折りたたんだり出来る為、
  RHTMLが展開後どうなったなどが見やすい。
2、AJAXにより書き換えられた様子が見られる。
3、RJSなどで送ったスクリプトが間違っていないか解る。

RailsでのAJAX利用には欠かせないと感じます。
是非お試しを。

Firebug : リンク