9

私はRails 3で作業しており、複数の子テーブルを持つテーブルを持っています.

class Foo < ActiveRecord::Base
  has_many :things
  has_many :items
  has_many :widgets
end

class Thing < ActiveRecord::Base
  belongs_to :foo
end

class Item < ActiveRecord::Base
  belongs_to :foo
end

class Widget < ActiveRecord::Base
  belongs_to :foo
end

特定の Foo が 1 つ以上のテーブルに子レコードを持っているかどうかを確認する簡単な方法はありますか? 基本的に、これを行うためのより良い方法はありますか:

if !foo.things.empty? or !foo.items.empty? or !foo.widgets.empty?
  puts "This foo is in use!"
emd
4

6 に答える 6

6

これがany?目的です。

class Foo < ActiveRecord::Base
  def children?
    things.any? || items.any? || widgets.any?
  end
end

これは論争の的になっているので、私はあなたに提示します:

> foo = Foo.last
Foo Load (0.6ms)  SELECT "foos"......
> foo.items
Item Load (0.9ms)  SELECT "items".*.......
> foo.items.any?
=> true #OH, WHAT's that? NO SQL CALLS? GEE WILLICKERS
> foo.items.exists?
Item Exists (0.5ms) #Hmmmmmm....
=> true

ここでのポイントは、常にメモリにロードされている場合、どのような状況でもexistsDB 呼び出しを行うということです。何度も言ったように、重要なのは DB 呼び出しの効率ではありません(そして、SQL 呼び出しのほうが効率的です)。アドバンテージ。自分で探してください:any?spacesexists?any?

[20] pry(main)> Benchmark.measure { foo.item.exists? }
  Item Exists (0.5ms)  SELECT 1 AS one FROM "items" ...
=> #<Benchmark::Tms:0x007fc1f28a8638
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=0.002927,
 @stime=0.0,
 @total=0.00999999999999801,
 @utime=0.00999999999999801>
[21] pry(main)> Benchmark.measure { foo.items.any? }
=> #<Benchmark::Tms:0x007fc1f29d1aa0
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=7.6e-05,
 @stime=0.0,
 @total=0.0,
 @utime=0.0>

より簡潔なタイミングについては、これを見てください。

> Benchmark.measure { 1000.times {foo.items.exists?} }.total
=> 2.5299999999999994
> Benchmark.measure { 1000.times {foo.items.any?} }.total
=> 0.0

何度も言ったように、状況によって異なります。これらの項目がメモリに読み込まれない状況が多くありますが、多くの場合、読み込まれます。呼び出し方に応じて、最適なものを選択してください。

于 2013-09-04T22:17:38.570 に答える
5

これは、任意のモデルで機能するはずです。

class Foo < ActiveRecord::Base
  def children?
    has_associated_records = self.class.reflect_on_all_associations.map { |a| self.send(a.name).any? }
    has_associated_records.include?(true)
  end
end
于 2013-09-04T22:43:47.877 に答える
0

Thing Item と Widget をサブクラス化できます。または、多態的な結合テーブルを追加して追跡します。理想的ではありません。

少なくともこれを行うことができたので、もう少し読みやすくなります。

if foo.things.exists? || foo.items.exists? || foo.widgets.exists?
  puts "This foo is in use!"
end

'空の?' 「存在しますか?」を使用します 舞台裏で、私は信じています。

于 2013-09-04T22:05:26.990 に答える
0

すべての関連付けがメモリに読み込まれているとします。

class Foo < ActiveRecord::Base
  has_many :things
  has_many :items
  has_many :widgets

  def in_use?
    [things, items, widgets].flatten.any?
  end
end

編集

これが間違っていることに気付きました: 各関連付け (メモリにまだ読み込まれている場合でも) が読み込まれますが、これは良くありません。

things.any? || items.any? || widgets.any?

はより正確であり、私の前に提案されています。

于 2013-09-04T22:40:03.697 に答える