嵌套表单模型 - 运行条件操作

时间:2013-11-24 21:54:30

标签: ruby-on-rails forms activerecord controller

在我的Rails应用程序中,我有步骤和问题。用户可以为任何步骤生成问题。

Step.rb

class Step < ActiveRecord::Base 
    has_one :question, :dependent => :destroy
    accepts_nested_attributes_for :question, :allow_destroy => :true
end

Question.rb

class Question < ActiveRecord::Base
    belongs_to :step
end

我使用嵌套表单生成一个问题:

  <%= semantic_form_for [@project,@step] do |f| %>
     <%= f.fields_for :question do |question_f| %>
         <%= question_f.text_area :description %>
     <% end %>
  <% end %>

首先,如果用户实际在问题文本区域中输入文本,我只想创建一个新问题。如何防止步骤表格自动保存空白问题?这是我当前的步骤控制器:

  class StepsController < ApplicationController
      def new
         @step = @project.steps.build(:parent_id=> params[:parent_id])
         @step.build_question
         ...
      end

      def create
        @step = @project.steps.build(params[:step])
        respond_to do |format|
          if @step.save
          ...
      end
   end 

其次,我想在创建新问题时运行一些ruby代码。特别是,我想更新包含问题的项目的updated_at日期。我会把它放在我的控制器里?我尝试为Question模型创建一个控制器并创建create和new方法,但是在提交步骤表单时没有调用它们。

1 个答案:

答案 0 :(得分:2)

您的第一个问题可以通过修改Step类中的嵌套属性行来解决,如果其属性全部为空,则拒绝提交的问题,如下所示。请参阅:reject_if 下的accepts_nested_attributes_for文档。

accepts_nested_attributes_for :question, :reject_if => :all_blank, :allow_destroy => true

你的第二个问题可以通过多种方式解决。如果始终想要在添加问题时更新项目的updated_at(也称为“触摸”它),则可以向Question添加回调接触项目的班级。 See this guide on callbacks

class Question < ActiveRecord::Base
  belongs_to :step
  has_one :project, :through => :step

  after_create :touch_project

  private

  def touch_project
    project.touch
  end
end

另一方面,如果您只想在特定控制器操作的上下文中触摸问题的项目,您可以检查问题是否已创建,如果是,则触摸项目:

def create
  @step = @project.steps.build(params[:step])
  if @step.save
    if @step.question.present?
      @project.touch
    end
    # do other stuff for successful save
  else
    # handle failed save
  end
end

此外,为了将来参考,如果你有两个很大程度上无关的问题,最好分别问他们。结合问题会使具有相同问题的其他人更难找到答案。