从控制器实例化辅助方法中的实例变量

时间:2014-02-06 15:04:10

标签: ruby-on-rails scope instance-variables partials

我有一个帮助器,它实例化一个模型并呈现一个表单。此表单应该可用于应用程序中的任何视图

# support_form_helper
def support_form
  @support_stats = SupportForm::Stat.find(get_stats_id)
  @enquiry = SupportForm::Enquiry.new(stats_id: @support_stats.id)
  render partial: 'support_form/enquiries/form'
end

它在视图中呈现:

# some_view.html.erb

<%= support_form %>

这是好的,直到我想提交表格并在控制器中验证它。

# enquiries_controller.rb
def create

  @enquiry = SupportForm::Enquiry.new(params[:support_form_enquiry])

  topic = @enquiry.topic
  @stat = SupportForm::Stat.find(@enquiry.stats_id)

  @stat.stats[topic] = @stat.stats[topic].to_i.next
  respond_to do |format|
    if @enquiry.valid? && @stat.save
      format.html { redirect_to(root_path) }
    else
      format.html { redirect_to(:back) }
    end
  end
end

这是我无法使用附加到无效对象的错误渲染上一个视图的地方。再次调用帮助程序并初始化一个新的@enquiries对象,显然没有错误。

如何在应用程序的多个视图中呈现表单,并且当对象无效时仍然返回带有对象的视图?


我找到了一个答案来回答我的问题,但这是个坏主意:

Render the action that initiated update

def创建       @enquiry = SupportForm :: Enquiry.new(params [:support_form_enquiry])

  topic = @enquiry.topic
  @stat = SupportForm::Stat.find(@enquiry.stats_id)

  @stat.stats[topic] = @stat.stats[topic].to_i.next

  if @enquiry.valid? && @stat.save
    redirect_to(root_path)
  else
    render Rails.application.routes.recognize_path(request.referer).values.join("/")
  end
end

问题是视图中可能存在提交表单的实例变量,我必须能够在应用程序中实例化所有实例变量然后.....不可能。

目前我正在考虑将错误放在flash哈希中......不是我想做的事情。返回原始对象后,我可以使用用户输入重新填充字段。

1 个答案:

答案 0 :(得分:0)

使用redirect_to时,rails将启动一个全新的控制器&amp;查看序列。使用

渲染“path / to / template / from / view / folder”`

代替。

使用此模式的典型创建操作看起来像(在这种情况下为'post'对象):

def create
  @post = Post.new(params[:post])
  @created = @post.save
  respond_to do |format|
    if @created
      flash[:notice] = 'Post was successfully created.'
      format.html { redirect_to post_path(@post) }
      format.js
    else
      format.html { render :action => :new }
      format.js
    end
  end
end 

注意如果它成功创建我们如何完全重定向到帖子的“show”页面,但是如果它不成功我们只是做一个渲染。

您可能应该修改您的support_form帮助程序,以便它只创建一个新的@enquiry(如果尚未创建):

def support_form
  @support_stats = SupportForm::Stat.find(get_stats_id)
  @enquiry ||= SupportForm::Enquiry.new(stats_id: @support_stats.id)
  render partial: 'support_form/enquiries/form'
end

|| =是“等于自己或”的简写。如果它尚未被定义(或者是nil或false),那么它将在or的第一部分失败并且传递到创建对象的第二部分。

在您的表单中,您还应该确保使用的是form_for,它将根据对象是否已经保存而提交给创建或更新操作。