[英]finding parent in rails polymorphic association
I am working on implementing polymorphic comments (these can be applied to just about any user content on the site, and is not limited to Article
instances. When creating a comment, I need to determine which commentable
it belongs to. Most of the writing I have found on this subject suggests that I use the pattern specified in find_commentable
in the code below, but this approach does not strike me as very elegant - it would seem there should be a straightforward way to unambiguously specify the commentable
a new comment is being created for, without traversing the params
set, and without string matching. Is there a better way? 我正致力于实现多态注释(这些注释可以应用于网站上的任何用户内容,并且不仅限于
Article
实例。在创建注释时,我需要确定它属于哪个可commentable
。大多数写作我我已经在这个问题上发现我在下面的代码中使用了find_commentable
中指定的模式,但是这种方法并没有让我觉得非常优雅 - 似乎应该有一种直接的方法来明确指定可commentable
的新注释正在被创建因为,没有遍历params
集,没有字符串匹配。有更好的方法吗?
In other words, is there a better way to access the commentable
object from the comment
controller in the context of a commentable
→ comment
association? 换句话说,是否有更好的方法在
commentable
→ comment
关联的上下文中从comment
控制器访问可commentable
对象? Does it still work the create
method where we do not yet have a @comment
object to work with? 它仍然适用于我们尚未使用
@comment
对象的create
方法吗?
My models are set up as follows: 我的模型设置如下:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Article < ActiveRecord::Base
has_many :comments, :as => :commentable, dependent: :destroy
end
class CommentsController < ApplicationController
def create
@commentable = find_commentable
@comment = @commentable.comments.build(comment_params)
if @comment.save
redirect_to :back
else
render :action => 'new'
end
end
def index
@commentable = find_commentable
@comments = @commentable.comments
end
private
def comment_params
params.require(:comment).permit(:body)
end
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
end
end
Thank you! 谢谢!
I was looking for an answer to this as well and wanted to share Launch Academy's Article on Polymorphic Associations as I felt it provided the most succinct explanation. 我也在寻找答案,并希望分享Launch Academy关于多态关联的文章,因为我觉得它提供了最简洁的解释。
For your application two additional options: 对于您的应用,还有两个选项:
1. The "Ryan Bates" Method: (when you use Rails' traditional RESTful URLs) 1.“Ryan Bates”方法:(当您使用Rails的传统RESTful URL时)
def find_commentable
resource, id = request.path.split('/')[1, 2]
@commentable = resource.singularize.classify.constantize.find(id)
end
2. The Nested Resource: 2.嵌套资源:
def find_commentable
commentable = []
params.each do |name, value|
if name =~ /(.+)_id$/
commentable.push($1.classify.constantize.find(value))
end
end
return commentable[0], commentable[1] if commentable.length > 1
return commentable[0], nil if commentable.length == 1
nil
end
3. The Single Resource: (Your implementation but repeated for completion) 3.单一资源:(您的实施,但重复完成)
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
I would do it the other way round - make the comment then define commentable. 我会反过来做 - 然后让评论定义可评论。
@comment = Comment.create(params[:comment]) #this is the standard controller code for create
@commentable = @comment.commentable
I took Ryan Bates idea and tweaked it a bit. 我接受了Ryan Bates的想法,并稍微调整了一下。 I have some deeper scoped and nested resources.
我有一些更深入的范围和嵌套资源。
id, resource = request.path.split('/').reverse[1,2]
@commentable = resource.singularize.classify.constantize.friendly.find(id)
The idea here is that you are stripping off the parent from the end of the path. 这里的想法是你从路径的末尾剥离父母。
So if your path is /scope/resource_a/1234/resource_b/5678/comments
etc. no matter how deep you nest that you always get the top level parent. 因此,如果你的路径是
/scope/resource_a/1234/resource_b/5678/comments
等,无论你有多深,你总是得到顶级父级。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.