Trabalhando com tabelas auxiliares de banco de dados em trilhos, muitas vezes vejo carregamento de dados muito abaixo do ideal nos controladores (especialmente para índice) que resulta em baixo desempenho do aplicativo. Use inclui e junta , eles são seus amigos!
class Item
belongs_to :user
end
class User
has_many :items
def permissioned_name
if can_see?
name
else
"Mister"
end
end
def can_see?
Time.now == Time.now.midnight # shows real name only on midnight
end
end
Isso geralmente é ruim em uma visualização de índice:
items = Item.all
items.each do |i|
i.user.name # this will result in a separate query for each user, N queries where N is Item.count
end
Como regra geral , as junções devem ser usadas quando precisamos de dados puros ou agregação de dados de outra tabela e inclui quando você precisa de dados + lógica.
Bom uso de incluir:
items = Item.includes(:users) # Loads all items, loads all users. Big memory and ActiveRecord init cost
items.each do |t|
i.permissioned_name # this will not result in N queries, since rails will preload users association
end
Uso subótimo de include, melhor do que não usá-lo:
items = Item.includes(:users) # Loads all items, loads all users. Big memory and ActiveRecord init cost
items.each do |i|
i.user.name # No additional query, but we are just taking one data field from user, why do we need all the heavy AR?
end
Use joins para acessar dados:
items = Item.joins(:users).group("item.id").select("items.*, count(users.id) as user_count")
# this will result in query like this:
# SELECT items.*, count(users.id) as user_count FROM `items` INNER JOIN `users` ON `items`.`user_id` = `users`.`id` GROUP BY items.id
items.each do |i|
i.user_count # notice that I can't use i.users.size, I have to use method user_count (which accesses the attribute loaded from DB)
end
Para se divertir, nunca use isso:
items = Item.includes(:users) # Loads all items, loads all users. Big memory and ActiveRecord init cost
items.each do |i|
t.users.count # N queries to DB for users count since count method is used!
end