fc2ブログ

2023.04 «  - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - - - » 2023.06
TOP > CATEGORY > RubyOnRails(Model)

TOP | NEXT

model のコールバック関数 

2008年08月20日 ()
モデルオブジェクトには、あらかじめコールバック関数が定義されています。

[model].create とか、[model].save とか、[model].destroy とかなどをしたときに、勝手に呼ばれるメソッドです。

例えば、

class User < ActiveRecord::Base
  validate_length_of :first_name, :maximum => 40

  def before_validation
    # ここに validate_length_of をする前に行っておきたい処理を書ける
  end
end



と書いておくと、コントローラ辺りで、

u = User.find(123)
u.first_name = 'ケロンパ'
u.save


とした時に、u.save の所で、first_name の validation が行われる前に、before_validation の中身が実行されます。

と言うわけで、挿入、更新、削除の場合、どんなコールバック関数が勝手に呼ばれてしまうのだろう、というのをまとめました。

上から下に順番に呼ばれます。


・挿入の場合 ([model].create とか [model].save とか)

before_validation
before_validation_on_create
# ここで validation が行われる
after_validation
after_validate_on_create

before_save
before_create
# ここで DB に挿入される
after_save
after_create




・更新の場合 ([model].save)

before_validation
before_validation_on_update
# ここで validation が行われる
after_validation
after_validate_on_update

before_save
before_update
# ここで DB が更新される
after_save
after_update




・削除の場合 ([model].destroy)

before_destroy
# ここで DB から削除される
after_destroy




てな訳です。どうしても隠れ機能が多い Rails ですが、腰元の帯をほどくように、あーれー、と1つ1つ丸裸にしてしまいましょう!

【広告】

スポンサーサイト



[2008.08.20(Wed) 00:13] RubyOnRails(Model)Trackback(0) | Comments(4) 見る▼
↑TOPへ


COMMENT

by xibbar
> 腰元の帯をほどくように、あーれー、と1つ1つ丸裸にしてしまいましょう!
この表現はエロイ!

R-18 by 自分
このブログはR-18なもので過激な表現を使用することがあります、なんちゃって。
生まれたままの姿は実に素敵ですね。

その3で質問したものです by -
説明ありがとうございました
これからもRailsのストリップ劇場期待してます^^;

なるほど by 自分
なるほど腰元風踊り子さんのストリップ劇場は新しいコンセプトかもしれません。
こちら、いつでも次ステージ開催準備が整っていますからまた質問があったら劇場窓口までお越しください。

コメントを閉じる▲

DBテーブル間の結びつき その3【has_one とか has_and_belongs_to_many とか】 

2007年10月30日 ()
DBテーブル間の関係としては、3種類ほどありまして、


ケース1 テーブルAの1レコードに対してテーブルBの1レコードが対応
ケース2 テーブルAの1レコードに対してテーブルBのたくさんのレコードが対応
ケース3 テーブルAのたくさんのレコードに対してテーブルBのたくさんのレコードが対応



とあります。Rails はそれぞれをモデルファイルで指定できます。

前回のエントリの都道府県テーブルと市区町村テーブルは、上記のケース2にあたりますね。

普段のエントリに漏れず、やはり例が分かりやすいと思うので、上記の3ケースの例を書いてみます。

ケース1 都道府県 (1) -> (1) 知事
ケース2 都道府県 (1) -> (たくさん) 市区町村
ケース3 都道府県 (たくさん) <-> (たくさん) 路線




今回は、上記のケース1と、ケース3をナイスカバー(©中山律子 in ザ・スターボウリング)してみたいと思います。

まず、ケース1

前々回作った都道府県テーブルを使用します。それから、新しく知事テーブルを作ります。

知事テーブル governors

+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| prefecture_id | int(11)      | YES  |     | NULL    |                |
| name          | varchar(255) | YES  |     | NULL    |                |
| age           | int(11)      | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+



そしてそして、知事モデルを追加します。

app/models/governor.rb

class Governor < ActiveRecord::Base
 belongs_to :prefecture
end



さらに、都道府県モデルに知事モデルのことを書きます。

app/models/prefecture.rb

class Prefecture < ActiveRecord::Base
  has_many :cities
  has_one :governor
end



じゃあ、これを書いたことで何できるの?というところですが、前回のように、belongs_to 側(知事側)から都道府県の操作をするのはつまんなーいので、都道府県側から知事側を操作します。ほいっ。

pref = Prefecture.find_by_name('東京都')
pref.create_governor(:name => '石原慎太郎', :age => 75)
pref = Prefecture.find_by_name('千葉県')
pref.create_governor(:name => '堂本暁子', :age => 75)
pref = Prefecture.find_by_name('埼玉県')
pref.create_governor(:name => '上田清司', :age => 59)
pref = Prefecture.find_by_name('神奈川県')
pref.create_governor(:name => '松沢成文', :age => 49)



石原さんが結構ご高齢なのですね。テレビでは若く見えます。


次に、ケース3

路線テーブルを作ります。

路線テーブル raillines

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| name        | varchar(255) | YES  |     | NULL    |                |
| train_color | varchar(255) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+




でも、この路線テーブルは、都道府県テーブルに結びつく外部キー prefecture_id を持っとらんですね、そう、このケースは中間テーブルが別に必要なのです。

都道府県-路線テーブル prefectures_raillines
(※1 アルファベット順に2つのテーブル名をつなげること!!)
(※2 auto_incrementのidカラムを作らないこと!!作ってしまうと、Mysql::Error: #23000Duplicate entry エラーがでて主キーが重なるときがある)
↑ちなみに、rake db:migrate では、:id => false を指定します

+---------------+---------+------+-----+---------+----------------+
| Field         | Type    | Null | Key | Default | Extra          |
+---------------+---------+------+-----+---------+----------------+
| prefecture_id | int(11) | YES  |     | NULL    |                |
| railline_id   | int(11) | YES  |     | NULL    |                |
+---------------+---------+------+-----+---------+----------------+



でも、この中間テーブル prefectures_raillines に対しては、モデルはいりません。

路線モデルを新規に追加、そして既存の都道府県モデルに1行書き足すだけでよろしかろう。

路線モデル
app/models/railline.rb

class Railline < ActiveRecord::Base
  has_and_belongs_to_many :prefectures
end



都道府県モデル
app/models/prefecture.rb

class Prefecture < ActiveRecord::Base
  has_many :cities
  has_one :governor
  has_and_belongs_to_many :raillines
end




以上をやりますと、都道府県に対する路線を簡単にDBに挿入できたりします。(その逆も簡単です。)

pref = Prefecture.find_by_name('東京都')
pref.raillines.create(:name => '山手線', :train_color => '緑')
pref.raillines.create(:name => '総武線', :train_color => '黄')
pref = Prefecture.find_by_name('千葉県')
rail = Railline.find_by_name('総武線')
pref.raillines.push(rail) # 千葉県と総武線を結びつける



という訳で、まだまだカバーし足りない部分(:through オプションとか・・・)もあるのですが、そちらは続編を書く気になれば書きますし、リクエストがあれば即書くと思います。(乗せられやすいから)

では、さらばー。

【広告】

[2007.10.30(Tue) 20:58] RubyOnRails(Model)Trackback(0) | Comments(0) 見る▼
↑TOPへ

DBテーブル間の結びつき その2【belongs_to の方のモデルで出来ること】 

2007年10月27日 ()
前回のエントリのように、都道府県テーブルと市区町村テーブルがあるときに、市区町村テーブルのモデル側から、その市区町村に結びつけながら都道府県も同時に作成できます。

と言っても、これまた分かりづらいでしょうから例で説明しますね。

DBとモデルは、前回と同じとします。

都道府県テーブルと市区町村テーブルにデータが入っていて、都道府県モデルが has_many、市区町村モデルが belongs_to なのでしたね。

そして、ここで「東京都港区の乱」が起きたと勝手に想定してみましょう。港区は、あまりに高い固定資産税の割に薄遇なのを不満に大阪府に寝返りました。というストーリーです。

港区を大阪府に寝返らせてみましょう。

ここでポイントは、

1.現状、都道府県テーブルに大阪府は入っていない
2.現状、港区は東京都として市区町村テーブルに登録されている

ですね。

なので、やることとしては、

1.都道府県テーブルに大阪府を追加する。
2.港区の都道府県IDを東京都から大阪府に更新する。

です。

今回 belongs_to 宣言をしたことによって、↑を実現するためのコードを、コントローラなどへ鮮やかに書くことができます。

しかもやり方が何通りがありますので、書いておきます。

その1 build_* を使うやり方

minatoku = City.find_by_name('港区')
minatoku.build_prefecture(:name => '大阪府', :katakana => 'オオサカフ') # この時点で何もDBは変わらない。
minatoku.save! # この時点で大阪府がDBに追加され、港区が大阪府になる



その2 = を使うやり方

minatoku = City.find_by_name('港区')
minatoku.prefecture = Prefecture.new(:name => '大阪府', :katakana => 'オオサカフ') # この時点で何もDBは変わらない。
minatoku.save! # この時点で大阪府がDBに追加され、港区が大阪府になる



その3 create_* を使うやり方

minatoku = City.find_by_name('港区')
minatoku.create_prefecture(:name => '大阪府', :katakana => 'オオサカフ') # この時点で大阪府がDBに入る。港区は東京都のまま。
minatoku.save! # これをやって初めて、港区が大阪府になる。



その1とその2が似ていますね。その3がちょっと違います。

てな具合で、スッキリとしたコードが書けるんだぞー、という訳でした。

おまけちゃん:
やっぱり港区は大阪府から東京都に返還になりました、をやりたい時

minatoku.prefecture = Prefecture.find_by_name('東京都')
minatoku.save!



次回は、has_one というものについて説明しようかな、なんて思っています。

【広告】

[2007.10.27(Sat) 21:15] RubyOnRails(Model)Trackback(0) | Comments(0) 見る▼
↑TOPへ

DBテーブル間の結びつき その1【イントロ】 

2007年10月23日 ()
railsのDBテーブルで、複数のテーブルを結びつけておくと、(・∀・)イイことがあります。

早速、例を見ていくに限る!(強引?)

都道府県テーブルと市区町村テーブルがあったとします。

都道府県テーブル prefectures

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment | 
| name     | varchar(255) | YES  |     | NULL    |                | 
| katakana | varchar(255) | YES  |     | NULL    |                | 
+----------+--------------+------+-----+---------+----------------+



市区町村テーブル cities

+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment | 
| prefecture_id | int(11)      | YES  |     | NULL    |                | 
| name          | varchar(255) | YES  |     | NULL    |                | 
| hiragana      | varchar(255) | YES  |     | NULL    |                | 
+---------------+--------------+------+-----+---------+----------------+



さらに、このテーブルには、以下のようにデータが入っていたとします。

都道府県テーブル prefectures

+----+--------------+--------------------+
| id | name         | katakana           |
+----+--------------+--------------------+
|  1 | 東京都       | トウキョウト       |
|  2 | 千葉県       | チバケン           |
|  3 | 埼玉県       | サイタマケン       |
|  4 | 神奈川県     | カナガワケン       |
+----+--------------+--------------------+



市区町村テーブル cities

+----+---------------+--------------+-----------------+
| id | prefecture_id | name         | hiragana        |
+----+---------------+--------------+-----------------+
|  1 |             1 | 港区         | みなとく        |
|  2 |             1 | 葛飾区       | かつしかく      |
|  3 |             1 | 世田谷区     | せたがやく      |
|  4 |             2 | 船橋市       | ふなばしし      |
|  5 |             2 | 我孫子市     | あびこし        |
|  6 |             3 | 草加市       | そうかし        |
|  7 |             3 | 和光市       | わこうし        |
|  8 |             4 | 川崎市       | かわさきし      |
|  9 |             4 | 鎌倉市       | かまくらし      |
+----+---------------+--------------+-----------------+




大事なのは、コ・コ・カ・ラ。ラブリーハート

都道府県モデルと、市区町村モデルに、それぞれの主従関係と対応関係を書いておきます。

1つの都道府県に、たくさんの市区町村が存在するので、都道府県モデルは、has_many を使います。

app/models/prefecture.rb

class Prefecture < ActiveRecord::Base
  has_many :cities # 複数形で書くこと
end



1つの市区町村は、ある都道府県に属しているので、belong_to を使います。ええと、もう少し詳しく説明すると、市区町村テーブルの中に、都道府県ID用のカラムがあるので、市区町村が都道府県に属していると判断して belong_to を使うようにします。

app/models/city.rb

class City < ActiveRecord::Base
  belongs_to :prefecture # 単数形で書くこと
end



さてさて、この has_many とか belong_to とかを書いて何が楽しいの?みたいになりますが、こうすることで自分と結びついているものを1行で書くことが出来ます。

といってもこれまた分かりづらいので、例を見ていくに限る!

例えば、東京都から、港区のひらがな読みが楽々参照できるという訳です。(主にコントローラからこの技を使うことが多いでしょう)

tokyo = Prefecture.find_by_name('東京都')
minatoku_hiragana = tokyo.cities.find_by_name('港区').hiragana # has_many だから city は複数形



てな感じです。

もし has_many と belong_to の記述をモデルにしていなかったら、次のようなまどろっこしいことをしなければ同じ事はできません。

tokyo = Prefecture.find_by_name('東京都')
minatoku_hiragana = City.find_by_prefecture_id_and_name(tokyo.id, '港区').hiragana



うーん・・・こうして並べて書いてみると、大して変わらないなあ orz

でも、1番目の方が2番目より分かりやすいですよね、パッと見。



そして、逆に、港区から東京都のカタカナ読みが楽々参照できます。

minatoku = City.find_by_name('港区')
tokyo_katakana = minatoku.prefecture.katakana # belongs_to だから prefecture は単数形



これが、has_many と belong_to の無い世界だと↓のようにまどろっこしく書かなくてはなりません。

minatoku = City.find_by_name('港区')
tokyo_katakana = Prefecture.find(minatoku.prefecture_id).katakana



やっぱりあまりまどろっこしさが伝わらない・・・orz

でも、1番目の方が2番目より分かりやすいですよね、パッと見。(しつこい?)



でもこれだけではないんです、has_* と belongs_to のすごさは。

それは次回以降に載せたいと思います。

じゃあ、チャオチャオっとチャオっちゃおー。バイバーイ by トマトちゃん

【広告】

[2007.10.23(Tue) 01:02] RubyOnRails(Model)Trackback(0) | Comments(0) 見る▼
↑TOPへ

validates_* の一覧 

2007年10月04日 ()
発作的に、入力チェック一覧を作りたくなりました。

使い方の基本のおさらい。モデルファイルに、

validates_XXXXXXXXX :カラム名

と指定します。その他いろんなオプションなど、詳しくは各メソッドに張ったリンクを参照してください(人任せ放任主義)

validates_acceptance_of
 「同意する」チェックボックスなどに使われる。仮想カラムを作って、DB の値チェックや DB への値更新は行わない。
 テーブルにカラムが定義されている必要もない。

validates_associated
 テーブル間の依存関係がうまくいっているかを調べる。

validates_confirmation_of
 メールアドレスのように、同じ値を2回いれてもらって、それが同じかどうかを調べる。
 指定したカラム名に、_confirmation という名前を加えた名前のフィールド名を view ファイルに作る。

validates_each
 独自のエラーチェックを行う。もちろん独自のエラーチェック方法は自分でシコシコと定義する。

validates_exclusion_of
 指定した範囲外だったらOK。範囲に入っていたらエラー。
 反対語は、validates_inclusion_of

validates_format_of
 正規表現にマッチするかを調べる。

validates_inclusion_of
 指定した範囲内だったらOK。範囲に入っていなかったらエラー。
 反対語は、validates_exclusion_of

validates_length_of
 文字列の長さを調べる。オプションにより、以上、以下、XからYまで、ちょうどXの長さ、など多彩に調べられる。

validates_numericality_of
 数字の長さを調べる。小数も整数もOK。整数のみ、というオプションもあります。

validates_presence_of
 空でなければOK。空だったらエラー。

validates_size_of
 validates_length_of と同じ。

validates_uniqueness_of
 指定したカラムの DB の値を見てみて、ダブっていたらエラー。ダブっていなかったらOK。


なんて具合でさぁ、親分。意外と数は少ないけれど、大抵のことはやれまさぁ。

【広告】

[2007.10.04(Thu) 00:31] RubyOnRails(Model)Trackback(0) | Comments(0) 見る▼
↑TOPへ

TOP | NEXT