Я пытаюсь отобразить список Active Records следующим образом:

<% @workout_sets.each do |workout_set| %>
  <tr>
    <td><%= workout_set.reps %></td>
    <td><%= workout_set.exercise.name %></td>
    <td><%= link_to 'Show', workout_set %></td>
    <td><%= link_to 'Edit', edit_workout_set_path(workout_set) %></td>
    <td><%= link_to 'Destroy', workout_set, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Моя настройка AR выглядит так:

class WorkoutSet < ActiveRecord::Base
  belongs_to :workout
  belongs_to :exercise, class_name: 'Exercise', foreign_key: 'exercises_id'
end

class Exercise < ActiveRecord::Base
end

class Workout < ActiveRecord::Base
  has_many :workout_set
end

И моя схема

create_table "exercises", force: :cascade do |t|
  t.string   "name",       null: false
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

add_index "exercises", ["name"], name: "index_exercises_on_name", unique: true

create_table "workout_sets", force: :cascade do |t|
  t.integer  "reps",         null: false
  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
  t.integer  "exercises_id"
 t.integer  "workouts_id"
end

add_index "workout_sets", ["exercises_id"], name: "index_workout_sets_on_exercises_id"
add_index "workout_sets", ["workouts_id"], name: "index_workout_sets_on_workouts_id"

create_table "workouts", force: :cascade do |t|
  t.string   "location",   null: false
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

При попытке отобразить страницу я получаю следующую ошибку

undefined имя метода для nil: NilClass

Когда я меняю путь в своем шаблоне на <%= workout_set.exercise %>, он отображает каждую строку как 444 #<Exercise:0x007fbde9dde998> Show Edit Destroy, что я и ожидал.

Почему попытка доступа к свойству name вызывает эту ошибку?

3
anger 24 Фев 2016 в 23:53

2 ответа

Лучший ответ

Один из ваших WorkoutSet не имеет связанного Exercise. Вы можете обеспечить, чтобы WorkoutSet имел упражнение Exercise в вашей модели WorkoutSet, но это имеет значение. В основном, вы не можете создать WorkoutSet, не создав предварительно Exercise. Если это то, что вы хотите, добавьте следующее к модели WorkoutSet.

validates_presence_of :exercise_id

Однако более вероятно, что вы просто хотите обработать сбой страницы, когда нет связанного Exercise.

<td><%= workout_set.exercise.name unless workout_set.exercise.blank?  %></td>

Это даст вам пустую ячейку, но вы можете сделать что-то вроде этого, чтобы иметь заполнитель.

<td><%= workout_set.exercise.blank? ? "No exercise for this set" : workout_set.exercise.name %></td>
2
James Klein 24 Фев 2016 в 21:13

Вы не установили отношения в модели упражнений

class Exercise < ActiveRecord::Base
  has_many :workout_sets
  has_many :workouts, through: :workouts_sets #not needed but good to setup
end

Или если вы пытаетесь установить связь 1: 1 между Exercise и WorkoutSet

class Exercise < ActiveRecord::Base
  has_one :workout_set
end

Кроме того, наличие символа «s» в конце внешних ключей в таблице workout_sets (т.е. «workouts_id») является несколько плохим тоном. Я почти уверен, что Rails будет достаточно умен, чтобы заставить его работать, но если вы столкнетесь с другими ошибками, я бы попытался изменить их на «workout_id» и «training_id».

0
SomeSchmo 24 Фев 2016 в 21:16