2015-12-11 5 views
2

У меня ошибка, которая, скорее всего, вызвана ассоциациями has_one в моей модели.has_one ассоциация и исчезающий идентификатор пользователя

Выпуск

После объявления этих ассоциаций я начал иметь странные взаимодействия, где я бы внезапно получить "undefined method электронную почту»для ноля: NilClass" `со следующим фрагментом из консоли ошибок:

<div class="row"> 

<div class="column-md-6 column-md-offset-3"> 

<% @posts.each do |post| %> 

    email: <%= post.user.email %> <br> # <= source of the issue! 

    Level: <%= post.level %> <br> 

    Region: <%= post.region %> <br> 

    Info: <%= post.description %> <br> 

    <% if post.user == current_user %> 

    <%= link_to "Edit", edit_post_path(post) %> 

Источник вопроса

Мне было трудно отслеживать ошибку и пытаться ее воспроизвести. быстро просмотрите мою базу данных в консоли rails и узнайте, что user_id становится нулевым, даже несмотря на то, что создание сообщения от пользователя прошло успешно. Я, наконец, удалось воспроизвести ошибку, выполнив следующие действия:

1) Вход

2) Создание Почте

3) Заходим в "все сообщения". Действие индекса индекса делает здесь все сообщения от каждого пользователя правильно.

4) Пока все еще зарегистрирован как один и тот же пользователь, создайте другое сообщение.

5) Вернитесь на «Все сообщения», и я получаю вышеупомянутую ошибку.

сообщение модель

class Post < ActiveRecord::Base 
    validates_presence_of :level, :region, :description 
    validates :level, length: { maximum: 50 } 

    belongs_to :user 
end 

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

class User < ActiveRecord::Base 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    has_one :post 
end 

сообщений контроллер

class PostsController < ApplicationController 
    before_action :set_post, only: [:edit, :update] 
    before_action :authenticate_user!, except: [:index, :show] 

    def index 
    @posts = Post.all 
    end 

    def show 
    @post = Post.find(params[:id]) 
    end 

    def new 
    @post = current_user.build_post 
    end 

    def create 
    @post = current_user.build_post(post_params) 
    if @post.save 
     flash[:success] = "Post successfully created!" 
     redirect_to posts_path 
    else 
     render 'new' 
    end 
    end 

    def edit 
    end 

    def update 
    #@post = Post.find(post_params) 
    if @post.update(post_params) 
     flash[:success] = "Profile updated" 
     redirect_to posts_path 
    else 
     render 'edit' 
    end 
    end 

    def destroy 
    Post.find(params[:id]).destroy 
    flash[:success] = "Post deleted" 
    redirect_to posts_path 
    end 

private 

def post_params 
    params.require(:post).permit(:description, :level, :region) 
end 

def set_post 
    @post = Post.find(params[:id]) 
end 

конец

schema.rb

ActiveRecord::Schema.define(version: 20151209193950) do 

    create_table "posts", force: :cascade do |t| 
    t.text  "description" 
    t.string "level" 
    t.string "region" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.integer "user_id" 
    end 

    create_table "users", force: :cascade do |t| 
    t.string "email",     default: "", null: false 
    t.string "encrypted_password",  default: "", null: false 
    t.string "reset_password_token" 
    t.datetime "reset_password_sent_at" 
    t.datetime "remember_created_at" 
    t.integer "sign_in_count",   default: 0, null: false 
    t.datetime "current_sign_in_at" 
    t.datetime "last_sign_in_at" 
    t.string "current_sign_in_ip" 
    t.string "last_sign_in_ip" 
    t.datetime "created_at",       null: false 
    t.datetime "updated_at",       null: false 
    end 

    add_index "users", ["email"], name: "index_users_on_email", unique: true 
    add_index "users", ["reset_password_token"], name:  "index_users_on_reset_password_token", unique: true 

end 

Вопрос

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

Если has_one является правильным способом, как я могу исправить эту проблему?

+0

Можете ли вы опубликовать свою схему db. –

+0

@PadmanabanGokula Обновлено мое оригинальное сообщение. – Lotix

ответ

2

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

Edit_0:
В общем, прямо перед кодом вы публикуемую добавить:

<%= debug params %> 

, чтобы увидеть, какие переменные вы отсутствующие/доступные в вашем представлении.

+1

Я думаю, что это правильно, если ошибка не возникает и при создании метода –

+0

Не могли бы вы поделиться куском кода вашего решения? Я пытаюсь это сделать, но мое действие редактирования разрывается. – Lotix

1

Поскольку вы упомянули, что у пользователя может быть только одно сообщение, вы должны проверить, нет ли у пользователя никакой почты перед созданием. Попробуйте, пожалуйста, ниже

def create 
    @post = current_user.build_post(post_params) unless current_user.post 
    if @post.save 
     flash[:success] = "Post successfully created!" 
     redirect_to posts_path 
    else 
     flash[:success] = "You exceeded your limit!" 
     redirect_to root_path 
    end 
    end 

, а также вы должны добавить предложение @benjamin, а также для редактирования действия.

1

В ваших новых действиях и действиях вы вызываете current_user.build_post, что имеет несколько неожиданный побочный эффект в Rails.

Сразу после присвоения или создания ассоциации has_one запускается запрос, который устанавливает внешний ключ для соответствующей модели на нуль. Невозможно остановить выполнение этого запроса в ассоциациях has_one. Если вы измените отношение на User на has_many, оно будет работать как ожидалось.

http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one#737-build-association-deletes-existing-dependent-record

Смежные вопросы