2016-03-01 4 views
0

Со следующими ассоциациями:модель, которая относится к более чем одной другой модели одновременно

class User < ActiveRecord::Base 
    has_many :posts 
    has_many :comments 
end 

class Post < ActiveRecord::Base 
    belongs_to :user 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :post 
end 

я могу сделать что-то вроде этого в контроллере:

@comment = current_user.comments.new(comment_params) 
@comment.user 

Но для доступа к соответствующим Post I необходимо вручную установить его родительское лицо:

@comment.post = Post.find params[:post_id] 

Есть ли лучший способ сделать t его, когда создается новый Comment?

+0

Ваши ресурсы вложены? Похоже, что они есть. –

+0

Нет, их еще нет. – Sajjad

+0

Можете ли вы предоставить свою схему для сообщений пользователя и комментариев? –

ответ

-2

Если вы хотите, чтобы объект комментариев был послан к одному или, тогда будет работать полиморфная ассоциация.

http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

class Comment < ActiveRecord::Base 
    belongs_to :commentable, polymorphic: true 
end 

class User < ActiveRecord::Base 
    has_many :posts 
    has_many :comments, as: :commentable 
end 

class Posts < ActiveRecord::Base 
    belongs_to :user 
    has_many :comments, as: :commentable 
end 

Вы не сможете использовать @ comment.post, но вы будете в состоянии сделать @ comment.commentable, который будет либо ваш пост или объект пользователя в зависимости от какой из связанные с этим экземпляром.

+1

В моем коде как 'Post', так и' User' связаны с 'Comment'. – Sajjad

+1

Он хочет, чтобы он принадлежал обоим, с несколькими 'own_to', насколько я понимаю, ни тем, ни другим. –

+0

> belongs_to может использоваться только один раз Вы ошибаетесь –

1

Я хотел бы использовать вложенные ресурсы

resources :posts do 
    resources :comments 
end 

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

class CommentsController 
    def new 
    @post = Post.find(params[:post_id]) 
    @comment = @post.comments.new 
    end 

    def create 
    @post = Post.find(params[:post_id]) 
    @comment = @post.comments.new(comment_params) 
    end 

    private 

    def comment_params 
    params.require(:comment).permit(:content).merge({ user_id: current_user.id }) 
    end 

end 

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

def comment_params 
    params.require(:comment).permit(:content) 
end 

def comment_creation_params 
    comment_params.merge({ user_id: current_user.id }) 
end 
+0

Я думаю, что это больше, чтобы отображать комментарии на странице показа сообщений, и кто их разместил. Что такое обратный вызов? Вы имеете в виду создание действия? Это то, что я говорю внизу. В действии create вы должны использовать '@comment = @ post.comments.new (comment_creation_params)' –

+0

Это разрешает этот частный случай, но добавляет еще одну проблему: я не могу сделать '@ comment.user' доступ к пользователю и обычно я не могу воспользоваться функциями, добавленными 'belongs_to: user' – Sajjad

+0

@Sajjad, почему бы и нет, просто добавьте в' own_to: user', тогда вы можете сделать '@ comment.user' –

0

Итак, основная идея просто получить избавился от Post.find(params[:post_id]).

Если бы я тебя, я бы вставить post_id в comment_params явно:

def comment_params 
    params.require(:comment).permit(:text).merge(post_id: params[:post_id]) 
end 

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

class Comment 
    validates :post, presence: true 
    #... 
end 

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

validate do 
    errors.add(:post_id, 'There is no post') unless Post.find(post_id).present? 
end 

Один из ответов предлагает решение с вложенными ресурсами, что является еще одним обходным решением.

+0

Проблема с моим кодом заключается в том, что я не могу использовать @ comment.post для доступа к assoicated сообщению, не связывая 'Комментарий' с' Post' – Sajjad

+0

@Sajjad, почему бы вам не добавить комментарий с сообщением, когда комментарий принадлежит сообщению по сути? –

+0

@ Саяд, я отредактировал свой ответ. Там нет необходимости добавлять валидацию вообще, 'comment_params' делает трюк. –

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