Category:Ruby

2008/03/14(Fri) 02:04 「Ruby on Rails 個人的メモ vol.7」
Railsのディレクトリ構造などなど。

app/
モデル、ビュー、コントローラのファイルはapp/のサブディレクトリに格納される

components/
再利用可能なコンポーネント(サイドバーとか)

config/
設定情報。データベースの接続パラメータなど

db/
スキーマ情報など

doc/
自動生成されたドキュメンテーション(rake appdoc)

lib/
共有コード

log/
実行中のアプリケーションによって生成される。
ログファイル(test, production, developmentでそれぞれ保存)

public/
Web経由でアクセス可能なディレクトリ。
アプリケーションはココから実行されるように見える

Rakefile
ドキュメンテーションとテストのビルドスクリプト

script/
ユーティリティスクリプトファイル
benchmarker
アプリケーション内のメソッドのパフォーマンスを計測
breakpointer
ブレークポイントが設定されたRailsアプリと通信しながら、
動作を対話的に調査(13.7節)
console
irbを利用する
destroy
generateによって作成されたファイルの削除
generate
コードジェネレータ。
サイトからモジュールをDLして追加も出来る。
profiler
アプリケーション内のコードを対象に、
実行時のプロファイルの要約を作成。
runner
アプリケーション内のメソッドをWebのコンテキスト外で実行。
cronジョブからキャッシュ失効化メソッドを呼び出したり、
受信したメールを処理したり出来る。
server
アプリケーションを実行するWEBrickベースのサーバー。

test/
テストユニット、機能テスト、モック、フィクスチャ

vendor/
サードパーティのコード。



vendorは、libと同じ目的で使用されるらしい。
ただし、libは開発者が作成したコードのディレクトリで、vendorはサードパーティ製のコードのためのディレクトリ。
Subversionを使っていれば、svn:externalsプロパティを設定すれば、これらのディレクトリに配置したコードを管理対称に含めることが出来る。
後方互換性を維持するため、libとvendorは自動的にロードパスに含められる。
コメント[書いてくれると喜びます]:
2008/03/14(Fri) 01:51 「Ruby on Rails 個人的メモ vol.6」
最近書く時間ないから纏めてメモ。


・型宣言での注意
decimal列を用いると、ActiveRecordではfloatクラスのオブジェクトにマッピングされるので丸め誤差が生じる
→int型を使ったほうが安全

Rubyのクラス SQLの型
Fixnum -> int,integer
Float -> decimal, numeric
Date -> interval, date
String -> clob, blob, text
Float -> float, double
String -> char, varchar, string
Time -> time, datetime


・モデルの中で属性の名前を受け取る(未確認)
read_attribute()、write_attribute()



Rubyで条件内での列の値をチェックするには、列の名前の後に疑問符をつけるようにする
Rubyでは、0とかfもtrueとして解釈するためです。
order = order_find_by_name("Dave")
if order.name?
grant_privileges
end



・特殊なテーブル命名をする場合の例
class Sheep < ActiveRecord::Base
# このクラスの従属テーブルはsheepsでなくsheepと判別される
set_table_name "sheep"
end



・不明なエラー
def sendとすると下記のようなエラーがでた。sentにすると問題なかったんだけど…なんでだろう。
We're sorry, but something went wrong.
We've been notified about this issue and we'll take a look at it shortly.



・レイアウト系
例1:
render(
# レンダリング対象の部分テンプレート名(_article.rhtml)
:partial => "article",
# 部分テンプレートに渡すオブジェクト
:object => @an_article,
# テンプレート内に別のローカル変数を設定
:locals => {
:authorized_by => session[:user_name],
:from_ip => @request.remote_ip,
},
)


例2:
render(
# レンダリング対象の部分テンプレート名
# _animal.rhtmlがレンダリング
:partial => "animal",
# リスト表示?(@article_listとかでもOK)
:collection => %w{ ant bee cat dog elk },
# スペース用(_spacer.rhtmlがレンダリング)
:spacer_template => "spacer"
)


storeコントローラのcart_summaryを実行
render_component(:controller => "store", :action => :cart_summary)

※この場合、layout "xxxx", :except => :cart_summaryといった例外処理を入れなければいけないっぽい

また、render_component_as_stringを使えば別のアクションを呼び出して、結果でレンダリングされたテキストを文字列として返す
サイドバーなので利用できそうだなー。


・開発環境でもキャッシュの生成を有効に(デフォルトはfalse)
config.action_controller.perform_caching             = true



・テンプレでの適用?
controller.rhtmlがlayoutに無い場合、application.rhtmlを代用するっぽい


以上。
コメント[書いてくれると喜びます]:
2008/03/14(Fri) 01:27 「Ruby on Rails 個人的メモ vol.5」
メールのフォーマットだけ(ぇ
def confirm(order)
# 件名
@subject = 'OrderMailer#confirm'
# ハッシュ(テンプレートでインスタンス変数として利用可)
# この場合orderが@orderとなる
@body["order"] = order
# 受信者
# @recipients = ['dave@dave.com', 'thomas '] or 'dave@dave.com'
@recipients = 'test@example.com'
# CC
# @cc = ''
# BCC
# @bcc = ''
# 文字コード(default: utf-8)
@charset = 'utf-8'
# 送信者
@from = 'anai@team-lab.com'
# ヘッダ
# @headers["Organization"] = 'Pragmatic Programers LLC'
@headers = {}
# 送信時刻の設定(Timeオブジェクト)
@sent_on = Time.now
end
コメント[書いてくれると喜びます]:
2008/03/14(Fri) 01:15 「Ruby on Rails 個人的メモ vol.4」
最近思ったこと:Railsという洞窟は、掘り下げて行くとどんどん奥の深さを知るだけだった。

誰だ!楽とか能天気なことほざいてたのは!
言うまでも無く、自分だ。

今回はDBの触りっぽい辺りを。
リレーション関係はすげー深い気がするので、次回で。


・モデルに属性を追加する際は、drop/createを使わずalterを用いる
スキーマを変更するだけで済む


主キー
ActiveRecord内では、カラム名がidでなくともプライマリキーであればidとして処理。
ordersテーブルのプライマリキーがisbnの場合でも、Order.find("12354")とすればisbnが12354のをとりだす。
※結合列ではidを使うべきではない


DBでの列の保存
ブロックを利用した場合
Order.new do |o|
o.name = "tester"
# ...
o.save
end

とすれば、ローカル変数を作らずに保存できる。

newじゃなくて、createを使えば最後にsaveしなくても保存される。複数でも可。
orders = Order.create([{
:name => "testerr"
:email => "test@doccomo.d"
:address => "122 445"
:pay_type => "check"
},
{
:name => "testerr"
:email => "test@doccomo.d"
:address => "122 445"
:pay_type => "check"
}])


ハッシュで利用すると、フォームから取得した値を格納しやすい。
普通にやるとこんな感じになるけど
at_order = Order.create(
:name => "testerr"
:email => "test@doccomo.d"
:address => "122 445"
:pay_type => "check"
)

パラメータをオブジェクトとして受け取るとこんなにスマートに。
order = Order.create(params)


・DBのクエリ実行時は、セキュアにするためにプレースホルダを利用すると良い
name = params[:name]
pos = Order.find(:all,
:conditions => ["name = ? and pay_type = 'po'", name])


こんなんでもアリ
name = params[:name]
pay_type = params[:pay_type]
pos = Order.find(
:all,
:conditions => ["name = :name and pay_type = :pay_type",
{:name => name, :pay_type => pay_type}])


さらに
pos = Order.find(:all,
:conditions => ["name = :name and pay_type = :pay_type", params])


・find検索
色々条件句があるから、とりあえず一括で載せてみる。
def Order.find_on_page(page_num, page_size)
orders = Order.find(
# または:first
:all,
# WHERE区
:conditions => "name = 'aaa'",
# ソートしてみる
:order => "pay_type, shipped_at DESC",
# 件数制限
:limit => page_size,
# オフセットも出来る
:offset => page_nume * page_size,
# ordersをliに命名、productsをprに命名後、結合
:join => "as li inner join products as pr on li.product_id = pr.id"
)
end



・生でSQLのクエリを投げる場合[find_by_sql]
orders = LineItem.find_by_sql(
"select line_items.* from line_items, orders" +
"where order_id = orders.id" +
"and orders.name = 'aaa'"
)



・条件を満たす行の数をカウント[count_by_sql]
count = LineItem.count_by_sql(
"SELECT count(*)"+
"from line_items, orders"+
"where line_items.order_id = orders.id"+
"and orders.name = 'aaa'"
)



・update_attributeで属性の値を変更し保存
変更する値が一つの場合はこんな感じ
order = Order.find(12)
update_attribute(:name, "aaa")


複数ならこんな感じ
order = Order.find(12)
update_attributes(:name => "aaa", :email => "aaa@aaa.com")


タイトルにJavaという文字が含まれるすべての商品の価格を10%値上げする場合
result = Product.update_all("price = 1.1 * price", "title like '%Java%'")



・行の削除
deleteはデータベースレベル、destroyはRailsレベルでの削除なので、destroyを使ったほうが安全。
要するに、destroyはコールバックが働くけど、deleteではSQLで直でやる感じ…ってコトだろうなぁ。


・インクリメント、デクリメント
痒い所に手が届く(ぇ
increment_counter(counter_name, id)

decrement_counter(counter_name, id)



・新規のオブジェクトかチェック
DBで既に存在するオブジェクトなのか確認
hogehoge.new_record?



・find検索では、こんな便利なのも
or検索は出来ないみたいだけど、テーブルに用意されたカラムをandで区切って一括で書けるようになっているらしい。
なんてヤツ。
user = User.find_by_name_and_password(name, password)



・モデルオブジェクトで使用できる属性を調べるには
orders = Order.find_by_sql("select name, pay_type from orders")
first = orders[0]
p first.attributes # => {"name" => "aaa", "pay_type" => "check"}
p first.attribute_names # => {"name", "pay_type"}
p first.attribute_present?("assress") # => false



まだ半分も理解できてない状況ですけど、とりあえずメモだ!(カス
コメント[書いてくれると喜びます]:
2008/03/13(Thu) 23:50 「RailsMyAdmin使ってみた。」
phpMyAdminRuby版、railsmyadminとか言うのを見つけたので使ってみました。
導入方法は以下の通り。つーか公式に書いてるのそのままやればいいだけだけどw

サクっとプラグインをインストール
$ ruby script/plugin install
http://railsmyadmin.googlecode.com/svn/trunk/my_admin/

モデルを作る感覚で叩いてみる
$ ruby script/generate my_admin

environment.rbの1番下に以下の記述を追加
## MY ADMIN CONFIG
require 'my_admin/my_admin_tool'

# If you only want certain models to be available to RailsMyAdmin,
# set :all_models to false and specify the desired models in MY_ADMIN_MODELS
MY_ADMIN_GLOBALS = {:all_models => true, :confirm_destroy => false}

# Uncomment the following line if you set :all_models to false above.
#MY_ADMIN_MODELS = [User, Content]
# Replace [User, Content] with your desired array of model classes that
# RailsMyAdmin should be restricted to.

# MY_ADMIN_AUTH must define a Proc object that takes as a paramater
# an ApplicationController instance variable (c - in the example below).
# If you have a method defined in your ApplicationController,
# 'admin_logged_in?' for example, the following sample code will
# authenticate against that method and only allow visitors to
# view RailsMyAdmin if the 'admin_logged_in?' method returns true.

MY_ADMIN_AUTH = Proc.new { |c| c.send('admin_logged_in?') }

で、Railsアプリケーションのサーバーを起動させて、ブラウザで以下のアドレス入力で完了
http://localhost:3000/my_admin/main


使ってみた感想は、prototype.js使ってAjax使ってますよー!的な感じでちょっとカッコよかったんだけど、idのセットとか結構不便だった。
Railsで作ってるならそこらへんの配慮もしてくれていいんじゃないかなぁと。
で、触ってて幾つか問題に出くわしたのでメモ。


・インストール後、一度削除した後に再度インストールしたらエラーが出た。
作成した後コントローラのアドレスを変更しようとして一度appから全部取り除いた後、再度インストールしようとしたら以下のエラーが出た。
C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
:in `gem_original_require': no such file to load --
my_admin/my_admin_tool (MissingSourceFile)

config/enviroment.rbに以下の行を追加していたためエラーが出ていた様子(ぐーぐるのソースコードで乗ってたヤツ)
## MY ADMIN CONFIG
require 'my_admin/my_admin_tool'
~中略~
MY_ADMIN_AUTH = Proc.new { |c| c.send('admin_logged_in?') }



・paginateが・・・
やっぱりrails2ではプラグイン化されているrailsmyadminを使う場合インストール必要・・・けど、インストール先のURLが死んでます。わざわざ調べるのも面倒です。
とりあえずRails1.0で入っているvendor/plugin/内のpaginageをそのままRails2.0のに投げた


・railsmyadminはRails1.0向けっぽい
end_form_tag使ってちゃダメじゃん!
app/view/my_admin/フォルダと、
vendor/plugins/my_admin_generators/my_admin/templates/views/my_admin/フォルダに入っているrhtmlのフォーム関係のタグを修正。
<% form_tag :action => hoge do -%>とか、<% end -%>の組み合わせに変えるって事ね。


・結論
使いづらい。1.0からあわせるのメドい。
-> 削除。


あと、ソースとかの記述をする際に[pre]タグ使うようにしました。
これで若干見やすくなったかなぁ。
コメント[書いてくれると喜びます]:
2008/03/08(Sat) 09:32 「Ruby on Rails 個人的メモ vol.3」
昨日も色々と役に立つ内容をチェキしたので、メモメモ。
これで、一応AWDwのアプリケーション構築までは読んだはず。

次回以降は、Active Recordの仕組み辺りを掘り漁っていこうかと思います。


・テスト駆動開発を行う理由
最初にコントローラを作成して、test/functionalで意図する操作を行う自動テストを先に書くことで、コードのフローを先に作れる。
そのテストに沿ったコードを書くことで、エラー等の問題の発生を防げる。


・エラー「Mysql::Error: #42000BLOB/TEXT column 'address' can't have a default value: 」の原因
$ rake test_units --trace

と入力すると
rake aborted!
Mysql::Error: #42000BLOB/TEXT column 'address' can't have a default value:

といった感じのエラーが出る原因なのですが、MySQLの仕様でtextとblobにはデフォルト値をもてないらしいので、テーブルの作成時にtextとblobはデフォルト値を持たせないようにすればOK。

[参考URL]
http://dev.mysql.com/doc/refman/5.1/ja/blob.html


・テストコマンド
test/unitフォルダ内にあるテストファイルを実行
$ rake test_units


test/functionalフォルダ内にある機能テストファイルを実行
$ rake test_functional


test_units, test_functionalの両方を実行
$ rake


-nオプションでメソッド名を指定。
この場合はtest_update()メソッドのみ実行。
$ ruby test/unit/product_test.rb -n test_update


-nオプションで正規表現を指定。
この場合はvalidateという単語が含まれているProductTestクラス内のメソッドを全て実行する。
$ ruby test/unit/product_test.rb -n /validate/


過去10分間に変更されたモデルやコントローラのみテストを実行
$ rake recent



・rakeコマンドあれこれ
統計情報(参考程度)
$ rake stats


サーバー起動コマンド。-eオプションで、起動するDBをセットできる。
developmentの部分は、test、productionなど適時変更
Apacheまたはlighttpdを使用している場合はRAILS_ENV環境変数を設定。
$ ruby script/server -e development


実行可能なすべてのタスクのリストが表示される。
rakeで何が使えるのかなー?と思ったら、まずはこのコマンド叩いてみるとよさげ。
$ rake --tasks



・カバレージのパーセント値で示したレポートをHTML形式で出力する
AWDwではRubyCoverageが紹介されていたのですが、動いてくれないので代用としてrcovを使用。

まずはインストール
$ gem install rcov

実行してみる
$ rcov test/functional/store_controller_test.rb

これで[Railsアプリケーションフォルダ\coverage]にhtmlが生成される。

こう打つとtextで出力してくれるらしいけど、こっちの方はまだ試してないw
$ rcov --no-html -t test/functional/store_controller_test.rb > coverage.txt



・速度チェック
Rails1.0以降と、それ以前で記述方法が若干違うらしいんですが、今回はRails1.0以降対象で。

指定したクラスの関数の実行速度実験。
$ ruby script/performance/profiler "Product.search('version_control')" 10


二つの速度比較をしたい場合は、benchmarkerを使うみたい。
$ ruby script/performance/benchmarker 10 
"Product.search('version_control')" \ "Product.search_n('version_control')"

コメント[書いてくれると喜びます]:
Counter
counter
Comment Box
Site Search
New Topics
[400] Ruby on Rails 個人的メモ vol.7
[399] Ruby on Rails 個人的メモ vol.6
[398] Ruby on Rails 個人的メモ vol.5
[397] Ruby on Rails 個人的メモ vol.4
[396] RailsMyAdmin使ってみた。
[393] Ruby on Rails 個人的メモ vol.3
Sub Menu
Home
Site Map
Profile
Archives
MST Setting
Link
Oekaki BBS
Contact Me
Name:angel
Mail:anilizawa@hotmail.com
MSN:anilizawa@hotmail.com
Mixi:2953512
Skype:ksk_angel
Twitter

あわせて読みたい

正当なCSSです!

なかのひと

フィードメーター - uncertain world

Read Me!