Rails 4:左连接获取连接模型的值 [英] Rails 4: Left join getting values of joined model

查看:75
本文介绍了Rails 4:左连接获取连接模型的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 3 个模型:

class User < ActiveRecord::Base
  has_many :likes, :dependent => :destroy
end

class Movie < ActiveRecord::Base
  has_many :likes, :primary_key => :mid, :foreign_key => :item_id
end

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :movie, :foreign_key => :item_id, :primary_key => :mid
end

除了喜欢电影之外,用户还可以通过喜欢模型更改喜欢电影的一些样式选项,例如expand &固定.

Besides liking a movie the user can change some styling options of the liked movie via the Like Model, such as expand & pin.

# likes
+---------------------------------------+
| user_id | item_id | expanded | pinned |
|---------|---------|----------|--------|
|    1    |    1    |   true   |  true  |
|    1    |    2    |   false  |  true  |
+---------------------------------------+

# movies
+-----------------------+
|  title   | mid | year |
|----------|-----|------|
|  Avatar  |  1  | 2009 |
| Gladiator|  2  | 2000 |
|  Shrek   |  3  | 2001 |
+-----------------------+

在这个例子中,用户喜欢电影《阿凡达》和《阿凡达》.角斗士,同时更改电影状态(expandedpinned).

In this example, the user likes the movies Avatar & Gladiator, while changing the movie states (expanded, pinned).

现在,当我想在一个视图中显示所有 3 部电影时,我想以登录用户想要的方式显示电影的状态.(阿凡达 => 扩展 & 固定,角斗士 => 固定,史瑞克 => 没有)

Now when I want to show all 3 movies in a view, I want to show the states of the movies the way the logged in user intended to. (Avatar => expanded & pinned, Gladiator => pinned, Shrek => nothing)

到目前为止,我的解决方案是加载所有电影,然后检查查询每部电影的状态...这导致查询过多.

My solution so far was to load all movies, and then check querying the state of every movie... This resulted in far too many queries.

所需的表格如下所示:

+---------------------------------------------------------------+
| user_id | expanded | pinned | item_id / mid |  title   | year |
|---------|----------|--------|---------------|----------|------|
|    1    |   true   |  true  |       1       | Avatar   | 2006 |
|    1    |   false  |  true  |       2       | Gladiator| 2000 |
|   null  |   null   |  null  |       3       | Shrek    | 2001 |
+---------------------------------------------------------------+

我知道应该通过 includes 使用连接来构建查询.

I understand that the query should be built up with a join via includes.

                                                                # ( 1 )
movies = Movie.includes(:likes).where(:likes => {:user_id => current_user.id }).references(:likes)

但是在循环播放电影时,我似乎无法获取加入的likes 表的数据,例如expanded 状态:

But when looping through the movies, I can't seem to get the data of the joined likes table, such as the expanded state:

movies.each do |m|
  puts m.expanded
  puts m.likes.expanded
end
# => undefined method `expanded' for #ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Like:0x007fae7ea51f48

我似乎无法弄清楚出了什么问题.提前致谢!

I can't seem to figure out what is going wrong. Thanks in advance!

推荐答案

我认为 Rails 不太擅长给出解释性异常,但你应该尽量理解它们:

I think that Rails is not very good in giving explanatory exceptions, but you should try understanding them never the less:

# => undefined method `expanded' for #ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Like:0x007fae7ea51f48

所以,这个错误告诉你没有方法expanded你认为它应该在那里.

So, this error tells you that there is no method expanded where you think it should be.

编号.造成此类事情的一个原因是您自己的代码中存在错误!

Nr. 1 reason for this sort of things are bugs in your own code!

优秀的程序员总是会考虑他或她可能做错了什么,所以让我们看看您的代码:

A good programmer always thinks about what he or she might have done wrong, so let's look at your code:

m.likes.expanded

这里我们有一个 Movie 类的对象.从你提供的代码中,我们可以看出它has_many 喜欢.这就是为什么最后有一个 s 的原因.不是like,而是likes.所以它是一个对象列表.在这种情况下,它是从数据库连接的延迟加载的对象数组.在 Rails 中,这些由 ActiveRecord::Associations::CollectionProxy 处理.

Here we have an object of class Movie. From the code you provided, we can see that it has_many likes. That's why there is an s to the end. It's not like but likes. So it is a list of objects. In this case, it is a lazily loaded Array of objects joined from the database. In Rails, those are handled by ActiveRecord::Associations::CollectionProxy.

因此,您在该代理对象的实例上调用 expanded,但相反,您希望在 Like 的实例上调用它.

So you are calling expanded on an instance of that proxy object, but instead, you would like to call it on an instance of Like.

如果你想这样做,你也需要迭代那些,或者选择一个相关的,这可能就像当前用户所做的那样.

If you want to do that, you need to iterate over those as well, or pick the one that is relevant, which might be the like that the current user did.

这篇关于Rails 4:左连接获取连接模型的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆