Ошибка сообщает вам, что в этой строке:
@profile = @user.profile.build
@ user.profile равно нулю.
Поскольку вы еще не создали профиль, это имеет смысл. Вместо этого сделайте что-то вроде этого.
@profile = Profile.new(:user_id => @user.id)
Re: страница индекса вызывает исключение.
Вы определяете @users в вашем контроллере, а затем ссылаетесь на @user в ваших помощниках по пути. Кроме того, итерация по @users должна давать вам объекты User, а не Profile.
Похоже, вы пытаетесь использовать действие Profile # index для отображения списка пользователей. Это вроде нормально, не совсем в стиле REST. Однако я ожидал увидеть нечто подобное:
<% @users.each do |user| -%>
<% unless user.profile.blank? -%>
<%= h user.profile.name %>
<%= h user.profile.category %>
<%= link_to 'Go to profile', user_profile_path(user, user.profile) %>
<% end -%>
<% end -%>
@jdl был правильным в том смысле, что в ProfilesController # new нет объекта @ user.profile, поэтому вызов @ user.profile.build вызовет исключение nil.
Вы можете исправить это, выполнив создание нового объекта Profile с помощью
@user.profile = Profile.new
. Позже, если @user будет сохранен, он вызовет @ user.profile и внешние ключи будут установлены соответствующим образом.
Также в вашем ProfilesController, действия #index и #show являются добрыми странно. Обычно действие #index возвращает «список объектов», а #show отображает только один объект, конкретный объект с идентификатором. Однако ваш #index возвращает очень конкретный объект, потому что он выполняет User.find с определенным идентификатором. Кроме того, поскольку у пользователя есть только один объект Profile, не имеет смысла загружать его объект Profile с помощью ORDER BY. Должен быть только один, поэтому порядок не требуется. Кроме того, спорный вопрос, нужно ли вам явно загружать объект профиля, поскольку вы можете просто получить к нему доступ через @ user.profile, а ActiveRecord загрузит его по запросу. Итак, ваш новый #index выглядит примерно как
def index
@users = User.paginate(:all, :order = "created_at desc", :page => 1, :per_page => 10)
end
. Предполагается, что у вас есть плагин WillPaginate, но суть в том, что вы загружаете СПИСОК объектов, а не только один. На ваш взгляд, если вы выполняете итерацию по @users и вызываете .profile для элемента этого списка, ActiveRecord загружает связанный профиль на лету.
То же самое и для #show - нет необходимости явно загружать профиль.
def show
@user = User.find(params[:user_id])
end
хм .. Я подумал, что когда у пользователя много профилей, вы можете использовать:
@user.profiles.build
@user.profiles.create
когда у пользователя один профиль, вы должны использовать:
@user.build_profile
@user.create_profile
Не уверен, проверьте API