作为rails的新手,我在rails中实现了一个博客。有权限的用户可以在博客上发表评论。管理员还可以对博客发表评论并锁定讨论。出于这个原因,我想实现类似Github Close and comment
函数的功能。管理员可以对正在进行的讨论发表评论,可以锁定它或者可以命令并锁定它。这3个动作都是用2个按钮完成的。
我已经实现了一个客户端javascript函数,可以将按钮标题从Lock
切换到Lock and Comment
。我现在的问题是博客帖子和讨论帖与不同的控制器相关联。锁定在BlogController
内执行。讨论帖子使用DiscussionController
处理。
如何通过1个动作触发2个动作:
DiscussionController
BlogController
目前我已将这些行动分开了。创建由form.submit
完成的新帖子,该帖子与DiscussionController
相关联。锁定讨论由link_to
BlogController
完成。
如何结合这两项行动?
答案 0 :(得分:1)
很难说没有看到一些示例代码来更清楚地了解您想要实现的目标,但它听起来像是一个很好的封装候选者。
也就是说,在models
目录中创建一个处理锁定和注释的普通旧ruby类。然后,在其中一个控制器中,创建该类的新实例并对其执行某些方法。
这个想法是通过确保你的控制器不必太努力来保持简单。从本质上讲,您希望将大部分登录信息移到模型中,但在这种情况下,因为您要对两个模型执行操作,所以您需要将逻辑放在一个完全独立的类中。这是为了防止你的一个模型变得超级强大并占领世界。 (开个玩笑,我们只是想避免一个名为God object的错误编程模式。还有另一种称为Single Responsibility Principle的最佳实践,它进一步证明了为此创建一个新类。
例如,
# /app/models/lock_and_comment.rb
class LockAndComment
def initialize(discussion, comment_params, user)
@blog = discussion.blog # Assumes discussion belongs to blog
@discussion = discussion
@comment_params = comment_params
@user = user
end
attr_reader :blog, :discussion, :comment
def lock_and_comment!
@blog.class.transaction do
comment = @discussion.comments.build(comment_params)
comment.user = @user
comment.save # You may even want to put this and the above two lines in a seperate method and call it from here
@blog.lock! # Assuming .lock is defined in blog model
end
end
end
初始化块将让您使用.new
方法进行设置。然后,致电.lock_and_comment!
。 @blog.class.transaction
确保如果对讨论进行评论或锁定博客存在问题,则不会发生任何问题。以下是控制器中可能出现的示例:
class DiscussionsController < ApplicationController
...
# POST /blog/:id/lock_and_comment, as an example route
def lock_and_comment
@discussion = Discussion.find(params[:id])
closing_comment = LockAndComment.new(@discussion, comment_params, current_user) # Assumes current_user is a user
if closing_comment.lock_and_comment!
redirect_to @discussion, notice: 'Locked and commented!'
else
redirect_to :back, alert: 'There was an error!'
end
end
end
这也假设您从模型中的方法锁定博客。如果您在BlogsController
中执行逻辑,则应该继续将其移至您的模式。他们所说的“肥胖模特,瘦瘦的控制者”。它还将提高控制器的可读性。这样,您的常规锁定方法如下所示:
class BlogsController < ApplicationController
...
def lock
@blog = Blog.find(params[:id])
if @blog.lock!
# do some things, etc etc etc
else
# process error
end
end
end
然后在你的Blog模型中:
class Blog < ActiveRecord::Base
...
def lock!
self.locked = true
self.save
end
end
希望它有所帮助。我就是这样做的。