1

我的模型如下所示:

class Movie < ActiveRecord::Base
  attr_accessible :title, :year, :rotten_id, :audience_score,
    :critics_score, :runtime, :synopsis, :link, :image

  has_many :jobs, :dependent => :destroy
  has_many :actors, :through => :jobs
end

class Actor < ActiveRecord::Base
  attr_accessible :name
  has_many :movies, :through => :jobs
  has_many :jobs, :dependent => :destroy
end

class Job < ActiveRecord::Base
  attr_accessible :movie_id, :actor_id

  belongs_to :movie
  belongs_to :actor
end

当我显示我的演员索引时,我想显示每个演员出演的电影数量。我可以用 来做到这一点@actor.movies.count,但是这会生成一个 SQL 查询each actor。假设有 30 个参与者,这将导致除了初始查询之外的 30 个额外查询。

有没有办法在最初的通话中包括每个演员参与的电影数量Actor.all?从而只需一个电话即可完成工作。如果这是按所述计数排序的额外奖励。

更新: 提供的所有答案都很有帮助,虽然它在某些时候变成了一些肮脏的比赛,但效果很好。我把你所有的建议混为一谈。我在我的 Actor 模型中添加了 movies_counter 列。在我的 Job 模型中,我添加了belongs_to :actor, :counter_cache => :movies_counter. 这非常有效,并且在我创建或销毁电影时会自动更新,而无需我添加任何进一步的代码。

4

2 回答 2

2

正如@Sam 所注意到的,您应该向actors表中添加新列movies_counter

rails g migration add_movies_counter_to_actor movies_counter:integer

现在您可以编辑您的迁移

class AddMoviesCounterToActor < ActiveRecord::Migration
  def self.up
    add_column :actors, :movies_counter, :integer, :default => 0

    Actor.reset_column_information
    Actor.all.each do |a|
      a.update_attribute :movies_counter, a.movies.count
    end
  end

  def self.down
    remove_column :actors, :movies_counter
  end
end

并运行它

rake db:migrate

然后你应该添加两个回调:after_saveafter_destroy

class Movie < ActiveRecord::Base
  attr_accessible :title, :year, :rotten_id, :audience_score,
    :critics_score, :runtime, :synopsis, :link, :image

  has_many :jobs, :dependent => :destroy
  has_many :actors, :through => :jobs

  after_save :update_movie_counter
  after_destroy :update_movie_counter

  private
  def update_movie_counter
    self.actors.each do |actor|
      actor.update_attribute(:movie_count, actor.movies.count)
    end
  end
end

然后你可以打电话some_actor.movies_counter

于 2011-03-19T21:54:36.890 回答
0

在您的 Actor 表中添加一个名为“movie_count”的列。然后在您的 Actor 模型中添加一个回调来更新该列。

class Movie < ActiveRecord::Base
  has_many :actors, :through => :jobs
  before_save :update_movie_count
  def update_movie_count
     self.actor.update_attribute(:movie_count, self.movies.size)
  end
end

这样,您只需更新一个整数,而不是调用所有记录。

于 2011-03-19T21:55:20.343 回答