【发布时间】:2017-04-19 09:17:27
【问题描述】:
我有一个 Meetup 模型 has_many :rsvps 和 Rsvp 模型 belongs_to :user。
这是我的终点:
def index(conn, _params) do
one_hour_ago = Timex.now
|> Timex.shift(hours: -1)
|> Timex.to_unix
meetups = from(m in Meetup, where: m.timestamp >= ^one_hour_ago)
|> Repo.all
|> Repo.preload(:rsvps)
render conn, meetups: meetups
end
我的看法
def render("index.json", %{ meetups: meetups }) do
render_many(meetups, ParrotApi.MeetupView, "meetup.json")
end
def render("meetup.json", %{ meetup: meetup }) do
%{
id: meetup.id,
rsvped_users: Enum.map(meetup.rsvps, fn rsvp ->
rsvp |> Repo.preload(:user)
user = rsvp.user
%{
image_url: user.image_url,
interests: user.interests,
}
end),
}
end
但是,** (Plug.Conn.WrapperError) ** (KeyError) key :image_url not found in: #Ecto.Association.NotLoaded<association :user is not loaded> 失败
将Repo 导入视图感觉不对。有没有办法在控制器中做到这一点?
【问题讨论】:
-
在控制器中做
|> Repo.preload(rsvps: [:user])怎么样? -
成功了!!!哇!谢谢!!
-
我建议不要在视图中预加载 - 这会导致很多痛苦和性能问题。视图应该是纯函数 - 没有副作用 - 这使得它们非常容易测试,可缓存等。您的实现也受到 N+1 查询的影响 - 对于每个 rsvp,您将为用户单独查询。从控制器执行此操作只会发出一个查询。
标签: elixir phoenix-framework ecto