Создание ассоциаций моделей Rails для has_many и own_to - PullRequest
6 голосов
/ 27 января 2012

Хорошо. Я новичок в 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" в действие index перед response_to. Довольно круто!

Что если я захочу перечислить все эти статьи (, для простоты я пропускаю здесь пейджинг ) на моей домашней странице, используя действие index на контроллере Home?

Я знаю, что могу сделать что-то подобное в Home Controller:

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

… и тогда я могу получить доступ к этим данным в моем домашнем-> индексном представлении:

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

Второй вопрос: В моем шаблоне для Article (построение миграции) я должен использовать user_id: integer или user: reference. Они делают то же самое, или один предпочтительнее другого? Если я использую: integer в качестве типа поля, рекомендуется ли мне также добавить индекс для него (add_index: article,: user_id)? Я нашел отличный RailsCast , и он отлично объясняет, но мне интересно, есть ли у кого-то еще мнение.

Если это поможет, я на Rails 3.2.2.

Спасибо!

Ответы [ 2 ]

5 голосов
/ 27 января 2012
  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
3 голосов
/ 27 января 2012

Первый вопрос:

Если вы хотите получить все статьи с данными о пользователях эффективным способом, вы должны использовать

@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. Индекс для столбца "article.user_id" улучшит скорость поиска при поиске статей определенного пользователя. Добавляйте этот индекс только в том случае, если ваше приложение будет выполнять такой поиск.

...