具有以下关联:
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
,我需要手动设置它的父级:
@comment.post = Post.find params[:post_id]
创建新Comment
时,有更好的方法吗?
答案 0 :(得分:1)
我会使用嵌套资源
resources :posts do
resources :comments
end
然后我会通过帖子构建评论并合并当前用户的ID,这样你就不需要隐藏的字段,这些字段显然可以被操纵。
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
答案 1 :(得分: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
其中一个答案表明使用嵌套资源的解决方案,这是另一种解决方法。
答案 2 :(得分:-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,它将是您的Post或User对象,具体取决于与该实例关联的对象。