使用1个帖子执行多个操作

时间:2014-08-02 21:13:48

标签: ruby-on-rails ruby ruby-on-rails-4

作为rails的新手,我在rails中实现了一个博客。有权限的用户可以在博客上发表评论。管理员还可以对博客发表评论并锁定讨论。出于这个原因,我想实现类似Github Close and comment函数的功能。管理员可以对正在进行的讨论发表评论,可以锁定它或者可以命令并锁定它。这3个动作都是用2个按钮完成的。

我已经实现了一个客户端javascript函数,可以将按钮标题从Lock切换到Lock and Comment。我现在的问题是博客帖子和讨论帖与不同的控制器相关联。锁定在BlogController内执行。讨论帖子使用DiscussionController处理。

如何通过1个动作触发2个动作:

  1. 发送表单DiscussionController
  2. 锁定BlogController
  3. 中的博文

    目前我已将这些行动分开了。创建由form.submit完成的新帖子,该帖子与DiscussionController相关联。锁定讨论由link_to BlogController完成。

    如何结合这两项行动?

1 个答案:

答案 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

希望它有所帮助。我就是这样做的。