为has_many和belongs_to创建Rails模型关联

时间:2012-01-27 18:09:08

标签: ruby-on-rails ruby-on-rails-3 migration associations reference

好的。我是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>

我对用户名的模型关联所需的只是放置&#34; @articles = Article.all&#34;在respond_to之前的索引操作上。非常酷!

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

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

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

...然后我可以在我的home-&gt;索引视图中访问此数据:

<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>

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

@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 个答案:

答案 0 :(得分:5)

  1. 您应该使用@articles = Article.all :include => :user来检索您的记录。有关为何通常比:joins更快的原因,请阅读Rails :include vs. :joins。 (基本上,它为您提供相同的信息,没有重复。)

  2. Rails在迁移方面有belongs_to关联的快捷方式。使用belongs_to :user,Rails将自动包含user_id列(integer类型)。

  3. 示例:

    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
    

答案 1 :(得分: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”列上的索引将在查找特定用户的文章时提高检索速度。仅当您的应用程序将执行此类搜索时才添加此索引。