创建Rails模型关联:has_many和belongs_to

6

好的..我是一个新手,对Rails不熟悉。我知道这个问题以前已经被问过了,但我仍然不清楚如何处理以下常见问题。我可以让关联工作,但让事情神奇地工作并且带着坏习惯启动rails并不是我想做的事情。

比如说我正在建立一个博客。我有两个资源:文章和用户。每个用户有很多文章,每篇文章属于一个用户:

rails g scaffold User name:string email:string
rails g scaffold Article user_id:integer title:string content:string

用户模型:

class User < ActiveRecord::Base
  has_many :articles
end

文章模型:

class Article < ActiveRecord::Base
  belongs_to :user
end 

现在,在我的文章索引页面,我可以做如下操作:
…table headers...
<% @articles.each do |article| %>
  <tr>
    <td><%= article.user.name %></td>
    <td><%= article.title %></td>
    <td><%= article.desc %></td>
    <td><%= article.content %></td>
    <td><%= link_to 'Show', article %></td>
    <td><%= link_to 'Edit', edit_article_path(article) %></td>
    <td><%= link_to 'Destroy', article, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

对于用户名的模型关联,我需要在响应前在索引操作中添加"@articles = Article.all"。非常酷!

如果我想在我的主页上使用Home控制器的索引操作列出所有这些文章(为简单起见,我跳过了分页),怎么办?

我知道我可以在Home控制器中做这样的事情:

class HomeController < ApplicationController
  def index
    @articles = Article.joins(:user)
  end 
end

然后我可以在我的home->index视图中访问这些数据:

<div class="row">
  <% @articles.each do |article| %>
    <div>
      <h3><%= link_to article.title,
        :controller => "articles", :action => "show", :id => article.id %></h3>
      <small>Posted on <%= article.created_at %> by
        <a href="#"><%= article.user.name %></a></small>
    </div>
  <% end %>
</div>

第一个问题:在访问所有文章的用户数据时,我应该使用:joins还是:includes?它们似乎都可以,但我想知道在这种情况下哪个是正确的,哪个通常执行得更快。

@articles = Article.joins(:user) 

-vs-

@articles = Article.includes(:user)
第二个问题: 在我为文章建立迁移的脚手架中,我应该使用user_id:integer还是user:references。它们是否具有相同的功能,或者一个比另一个更受推荐?如果我将字段类型设置为 :integer,那么是否建议我也为它添加索引(add_index :articles, :user_id)?我发现了一个很好的RailsCast,它做得很好地解释了这个问题,但我想知道是否还有其他人有不同的看法。

如果有帮助的话,我使用的是 Rails 3.2.2。

谢谢!

2个回答

5
  1. 您应该使用@articles = Article.all :include => :user来检索记录。请阅读Rails :include vs. :joins,了解为什么这通常比:joins更快。 (基本上,它可以为您提供相同的信息而不重复。)

  2. 当涉及到迁移时,Rails对于belongs_to关联有一个快捷方式。使用belongs_to :user,Rails将自动为您包含user_id列(类型为integer)。

例子:

class CreateArticle < ActiveRecord::Migration
  def self.up
    create_table :articles do |t|
      t.belongs_to :user # Creates 'user_id' column
      t.timestamps
    end
  end
end

谢谢!我之前不知道迁移中的“belongs to”简写,我一定会把它加入我的工具库。 - User 1058612

3

第一个问题:

如果你想高效地获取所有文章及其用户数据,则必须使用

@articles = Article.includes(:user)

您将获得您数据库中的所有文章列表,每篇文章都已获取其用户信息。

通过@articles = Article.joins(:user),您将仅获得具有用户的文章,当您对这些文章中的任何一篇文章执行article.user时,它将生成一个新的SQL请求。

更多信息请参考:http://guides.rubyonrails.org/active_record_querying.html(如果您尚未阅读此系列指南,我强烈建议您现在阅读)。

第二个问题:

我使用user_id:integer表单。我不确定user:references是否可以在rails g scaffold命令行中使用。在'articles.user_id'列上添加索引将提高检索速度,以便查找特定用户的文章。仅在应用程序需要进行此类搜索时才添加此索引。


感谢您的澄清。从日志中,我可以看到传递给我的数据库的查询,但我不确定Rails如何处理“includes”和“joins”。 “index”答案也非常有帮助! - User 1058612

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接