因此,在我正在开发的rails-api中,我们目前正在尝试优化一些较长时间运行的呼叫,并且我遇到了.includes功能的问题。我在大多数情况下都能使用它,但有一种特殊的情况是它没有以我想要的方式工作。
以下是一个例子:
用户类
class User < ActiveRecord::Base
has_many :images
has_one :active_image, -> { where(images: { active_image: true })}, class_name: 'Image'
has_many :facebook_auth
def get_profile_image
if active_image
active_image.image.url(:profile)
else
facebook = facebook_auth.last
if facebook
"https://graph.facebook.com/#{facebook.provider_user_id}/picture?width=150&height=150"
end
end
nil
end
end
控制器:
class UserController < BaseAPIController
def get_user_image
user_id = params[:user_id]
user = User.includes(:active_image, :facebook_auth).find(user_id)
render json: user.get_profile_image
end
end
有了这个,我会假设.includes(:active_image, :facebook_auth)
会缓存数据,这样当我在get_profile_image方法中调用它时,它不再进行db调用,但这不是案子。我在这里做错了什么?
谢谢, 查理
答案 0 :(得分:1)
你几乎就在那里! 试试这种方法:
class User < ApplicationRecord
has_many :images, dependent: :destroy
has_one :active_image,
-> { where(active: true) },
class_name: 'Image'
has_many :facebook_auths, dependent: :destroy
has_one :active_facebook_auth,
-> { order("created_at desc") },
class_name: 'FacebookAuth'
scope :eager_load_image_data,
-> { includes(:active_image).includes(:active_facebook_auth) }
def profile_image_url
if active_image
active_image.url
elsif active_facebook_auth
"https://graph.facebook.com/#{active_facebook_auth.provider_user_id}/picture?width=150&height=150"
else
nil
end
end
end
然后在你的控制器中,或者当你想要加载图像的时候:
# for one user, with id 2:
User.eager_load_image_data.find(2).profile_image_url
# for a collection (using 'all' here):
User.eager_load_image_data.all.map{ |user|
[user.name, user.profile_image_url]
}
这样就可以从 Image 类和 FacebookAuth 类中加载图像数据。
我修复了你的方法 User#get_profile_image 中的其他一些问题:
答案 1 :(得分:0)
嗯,我想发表评论,但是无法将代码放入评论中,所以我给出了一个不回答...
我没有看到任何明显错误,但作为一种解决方法,你可以在用户或某个地方做到这一点:
def self.user_profile_image(user_id)
active_image = Images.where(user_id: user_id).where(active_image: true).first
if active_image
active_image.image.url(:profile)
else
facebook = FaceBookAuth.where(user_id: user_id).last
if facebook
"https://graph.facebook.com/#{facebook.provider_user_id}/picture?width=150&height=150"
end
end
nil
end
只需调用/缓存控制器中的图像,如果这不是过于简单......
def get_user_image
render json: User.user_profile_image(params[:user_id])
end
这使得最多2个相对有效的查询。它不会不必要地加载用户等。