我的模特看起来像这样:
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
当我显示Actors的索引时,我想显示每个actor 已经加入的电影的数量。我可以使用@actor.movies.count
执行此操作,但这会生成each actor
的SQL查询。比方说,除了最初的30个演员之外,这将导致30个额外的查询。
有没有办法在最初的Actor.all
电话中包含每位演员参与过的电影数量?从而只用一个电话完成工作。如果这是按照所述计数排序的额外奖励。
更新
所提供的所有答案都很有帮助,虽然它在某些时候变成了一些肮脏的投标比赛,但结果很好。我做了你所有建议的混搭。我在我的Actor模型中添加了一个movies_counter列。在我的工作模型中,我添加了belongs_to :actor, :counter_cache => :movies_counter
。这非常出色,并且在创建或销毁电影时会自动更新,而不会添加任何其他代码。
答案 0 :(得分: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_save
和after_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
答案 1 :(得分: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
这样你只需要一个更新而不是调用所有记录的整数。