Rails, has_many, belongs_to

#ruby-on-rails #associations

#ruby-on-rails #ассоциации

Вопрос:

Схема:

   create_table "reports", :force => true do |t|
    t.integer  "user_id"
    t.string   "apparatus"
    t.string   "capt"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", :force => true do |t|
    t.string   "login",                     :limit => 40
    t.string   "name",                      :limit => 100, :default => ""
    t.string   "email",                     :limit => 100
    t.string   "crypted_password",          :limit => 40
    t.string   "salt",                      :limit => 40
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "remember_token",            :limit => 40
    t.datetime "remember_token_expires_at"
    t.string   "rank"
    t.integer  "shift"
    t.integer  "access"
  end
  

пользовательская модель:

 Class User < ActiveRecord::Base
    has_many :reports
#   bunch of other stuff thats not important
end
  

модель отчета:

 Class Report < ActiveRecord::Base
    belongs_to :user
end
  

просмотры / отчеты / индекс

 <% @reports.each do |report| %>
  <tr>
    <td><%= report.user_id %></td>  #     ****THIS IS THE LINE IN QUESTION****
    <td><%= report.apparatus %></td>
    <td><%= report.capt %></td>
    <td><%= report.body %></td>
    <td><%= link_to 'Show', report %></td>
    <td><%= link_to 'Edit', edit_report_path(report) %></td>
    <td><%= link_to 'Destroy', report, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
  

Я хотел бы иметь возможность отображать имя пользователя, создавшего отчет. Я предполагал, что объявление ассоциаций belongs_to и has_many сделает это возможным, написав report.user.name или что-то в этом роде. Где я ошибся?

Комментарии:

1. хорошо, проблема заключалась в том, что в моей таблице был один кортеж, у которого не было идентификатора пользователя. поэтому он зависал, пытаясь найти метод name на nil. Я задница.

Ответ №1:

Я на 99% уверен, что это связано с тем, что в одном или нескольких ваших отчетах нет связанного пользователя. Попробуйте

 <%= report.user.name rescue "none" %>
  

Если в поле user_id в отчете нет значения, то report.user будет возвращен nil. Это report.user.name было бы похоже на вызов nil.name , который вызывает ошибку.

ОБНОВЛЕНИЕ: вот лучший способ:

 <%= report.user.try(:name) %>
  

Ответ №2:

Вы можете сделать:

 <%= report.user.name %>
  

Но для повышения эффективности в вашем контроллере вы можете выполнить объединение, чтобы получить имя пользователя в том же запросе, который использовался для получения @reports .

Этот запрос может выглядеть примерно так:

 @reports = Report.select("reports.id as id, reports.apparatus as apparatus, reports.capt as capt, reports.body as body, users.name as user_name").joins("LEFT JOIN `users` ON `users`.`id` = `reports`.`user_id`")
  

Тогда ваш вывод будет выглядеть так:

 <%= report.user_name %>
  

Комментарии:

1. <%= report.user.name %> не работает. он выдает «имя неопределенного метода»»

2. хорошо, проблема заключалась в том, что в моей таблице был один кортеж, у которого не было идентификатора пользователя. поэтому он зависал, пытаясь найти метод name на nil. Я задница.

3. я немного опоздал, но рад, что вы это поняли!