Rails 4.0.2 select& uniq的

时间:2014-01-31 18:00:09

标签: activerecord ruby-on-rails-4

我正在使用此活动记录查询

CampaignType.includes(:campaign_description)
       .select('DISTINCT campaign_description_id, campaign_description.name')
       .where(:campaign_id => campaign_id)

曾经在rails 3上工作。现在它只是提供了许多DEPECATION警告和一个例子:

Currently, Active Record recognizes the table in the string, and knows to JOIN the comments table to the query, rather than loading comments in a separate query. However, doing this without writing a full-blown SQL parser is inherently flawed. Since we don't want to write an SQL parser, we are removing this functionality. From now on, you must explicitly tell Active Record when you are referencing a table from a string:

Post.includes(:comments).where("comments.title = 'foo'").references(:comments)

我尝试了一些不同的方法,但我没有到达那里。帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我无法解释为什么你得到了你在评论中提到的错误,因为我在我的最后做了同样的事情并且它正常工作。但是,实际上还有另一个问题可能会解决您的问题。

不幸的是,虽然技术上允许,但如果您同时使用includesselect进行预先加载,select实际上会被忽略(列不受限制,您得到一切的转储)。如果在这种情况下急切加载是一项重要要求,您应该能够使用preload方法而不是includes。所以你的查询看起来会更像这样:

campaign_type = CampaignType.preload(:campaign_description)
                .select("id, campaign_description_id, campaign_description.name")
                .joins(:campaign_description)
                .where(:campaign_id => campaign_id)
                .uniq

这会产生急切加载关联的campaign_description模型的效果,同时仍然只选择您指定的列。只要您的CampaignType模型允许访问非列属性,您就可以毫不费力地执行campaign_type.name之类的操作。请注意,最后的uniq会将DISTINCT修饰符添加到select子句中。

关于joins方法:不幸的是,您仍然需要包含此方法,否则Rails将不会隐式执行INNER JOIN,因此查询中对campaign_description的任何引用都将导致错误

另请注意,我在id中添加了select字段。这很重要,因为它是加载和访问关联的campaign_description行所必需的。如果您没有包含它,如果您尝试campaign_type.campaign_description(例如),则会收到一个空集合。

但是,在您的情况下,如果您只想返回仅包含DISTINCT个字段且不需要调用关联对象的模型,则可能根本不需要预先加载,并且可以安全地放弃preloadid部分。其他一切都会保持不变。