色々奥が深いと思った(not http://0xcc.net/misc/bad-knowhow.html 笑)

■前提:記事←関連テーブル→ユーザというモデル関係がある。
ruby>>

has_many :throughのパターン

class Article< ActiveRecord::Base
has_many :articles_users
has_many :users, :through => :articles_users
end

class User < ActiveRecord::Base
has_many :articles_users, :dependent => :destroy
has_many :articles, :through => :articles_users
end

関連テーブルを実テーブルで持つ

class ArticlesUsers < ActiveRecord::Base
belongs_to :article
belongs_to :user
end
<<ruby

■関連テーブルの操作

あるユーザの関連をごそっと別の関連に切り替えたいような場合!

User.articles_users.destroy_allして作り直すという方法もあるが
User.articles_users.replace()という便利なメソッドがある。

AWD第二版(AgileWebDevelopment)で言うとP308。
「○orders.replace(order1,...)
この顧客に関連付けられた注文のセットを、新しいセットに置き換える。現在の子のセットと新しいセットの違いを検出し、それに応じてデータベースの変更を最適化する。」という奴。

ruby>>
/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/associations/association_collection.rb

  # Replace this collection with +other_array+
  # This will perform a diff and delete/add only records that have changed.
  def replace(other_array)
    other_array.each { |val| raise_on_type_mismatch(val) }

    load_target
    other   = other_array.size < 100 ? other_array : other_array.to_set
    current = @target.size < 100 ? @target : @target.to_set

    @owner.transaction do
      delete(@target.select { |v| !other.include?(v) })
      concat(other_array.select { |v| !current.include?(v) })
    end
  end

<<ruby
これは便利。

1.配列を放り込むだけ

「Replace this collection with +other_array+」ということで検索結果、あるいはセッションなどで生成した新しい関連の配列を放り込むだけで使える。

2.以前の関連との差分をチェックして差分だけ反映してくれる。

「This will perform a diff and delete/add only records that have changed.」ということで必要な差分だけチェックして必要なdelete/addをしてくれる。

ちなみにdeleteだと「Railsレシピブック」のP157「Entryオブジェクトobjectとの関連を削除する。Entryオブジェクトobjectの外部キー(blog_id)をNULLにし、関連を削除する。複数の参照元オブジェクトを同時に指定できる。」にある通り、関連テーブルの実レコードは削除されない(外部キーがNULLになるだけ)。関連テーブルにごみが残って気持ち悪い場合は上記モデルのように「:dependent => :destroy」を付けると物理的に削除される。

posted by ysakaki ysakaki on Fri 22 Aug 2008 at 15:39 with 0 comments
Contents rssrss
榊祐介に関する最新情報について
「三鷹プログラマーズカフェβ」を始めます
MacのTerminal.appでSSHのセッション切れを防止するには
MacのNetbeans6.5でfast-debuggerを使用するには
Railsでテスト環境にdb:fixtures:loadするには
MacOS X(10.5)のNetBeans6.5でコミットエラーが出る場合
[Slicehost]MySQLとRuby/Railsの導入
WEBサービス用のapache設定を追加する
Slicehostと契約したら最初にやること
Excel で1行おきに色付けする方法
Tags
rails105macosxslicehostdebuggerExcelfixturesgemmysqlnetbeans65rakerubysvnterminalapp条件付き書式
Comments rssrss
satoko satoko: 私もGIMP入れてみたんですよ、で、同じ文字化け。 言語の優先順位を1.English、2:日本語... 11/28 07:38
榊 祐介 榊 祐介: >satokoさん コメントありがとうございます。 画像編集はGIMPを入れてみたのですがいきなり... 11/25 14:41
satoko satoko: しまったsubmitするの忘れてたのですが、昨日書いていたコメントです。^^ 11/19 10:59
satoko satoko: あわあわ、私も今日までずっと困っていました。先ほど別のところでこの設定方法を学んだところです!mac... 11/19 10:59
榊 祐介 榊 祐介: 検索したら自分のブログだった乙orz 11/11 15:07
naka54 naka54: こんにちは。先日は写真を撮影いただいてありがとうございました。 弊社でもこんなコースをやっていたりし... 09/10 19:02
瀧内元気 瀧内元気: どもども。こちらこそですー。 07/31 07:55
榊 祐介 榊 祐介: おー。瀧内さんお元気ですかー。 Rails勉強会とかでお世話になっております。 07/29 13:41